@agg-build/ui 4.17.3 → 4.18.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.
- package/dist/{chunk-7E4UXCEX.mjs → chunk-2OBJ7DYT.mjs} +1227 -534
- package/dist/{chunk-RZLM3M5R.mjs → chunk-2UPO6G3S.mjs} +1251 -2578
- package/dist/{chunk-DSQSQ4RG.mjs → chunk-FTWJRLJQ.mjs} +726 -3825
- package/dist/chunk-HFL3CEWG.mjs +3482 -0
- package/dist/{chunk-TK62UB5F.mjs → chunk-JJ3VVCEP.mjs} +6 -13
- package/dist/{chunk-B5ALKYD5.mjs → chunk-NRPS2D3Q.mjs} +176 -17
- package/dist/{chunk-BBDFSTIA.mjs → chunk-WIGSRHUG.mjs} +1532 -741
- package/dist/chunk-WSZYDOZN.mjs +2040 -0
- package/dist/{chunk-JI5KV4QI.mjs → chunk-ZNOAKSPT.mjs} +8 -10
- package/dist/event-market-GX24AP2H.mjs +21 -0
- package/dist/events.js +2960 -1523
- package/dist/events.mjs +6 -4
- package/dist/index.js +36141 -30748
- package/dist/index.mjs +34 -22
- package/dist/modals.js +1763 -1456
- package/dist/modals.mjs +5 -3
- package/dist/pages.js +34107 -28284
- package/dist/pages.mjs +17 -8
- package/dist/primitives.js +1552 -786
- package/dist/primitives.mjs +1 -1
- package/dist/styles.css +1 -1
- package/dist/tailwind.css +1 -1
- package/dist/trading.js +2559 -1499
- package/dist/trading.mjs +4 -4
- package/dist/types/events/item-details/event-chart-window.d.mts +9 -0
- package/dist/types/events/item-details/event-chart-window.d.ts +9 -0
- package/dist/types/events/item-details/event-list-item-details.types.d.mts +7 -0
- package/dist/types/events/item-details/event-list-item-details.types.d.ts +7 -0
- package/dist/types/events/item-details/event-markets-chart.d.mts +12 -0
- package/dist/types/events/item-details/event-markets-chart.d.ts +12 -0
- package/dist/types/events/item-details/event-markets-chart.utils.d.mts +23 -0
- package/dist/types/events/item-details/event-markets-chart.utils.d.ts +23 -0
- package/dist/types/events/list/event-list.constants.d.mts +2 -0
- package/dist/types/events/list/event-list.constants.d.ts +2 -0
- package/dist/types/events/market-details/use-visible-market-streams.d.mts +7 -0
- package/dist/types/events/market-details/use-visible-market-streams.d.ts +7 -0
- package/dist/types/events/shared/chart-source-caption.d.mts +4 -0
- package/dist/types/events/shared/chart-source-caption.d.ts +4 -0
- package/dist/types/events/shared/chart-venue-selection.d.mts +11 -0
- package/dist/types/events/shared/chart-venue-selection.d.ts +11 -0
- package/dist/types/events/shared/use-chart-orderbook.d.mts +23 -0
- package/dist/types/events/shared/use-chart-orderbook.d.ts +23 -0
- package/dist/types/onboarding/index.d.mts +1 -0
- package/dist/types/onboarding/index.d.ts +1 -0
- package/dist/types/onboarding/steps/connect-prophetx-modal.d.mts +12 -0
- package/dist/types/onboarding/steps/connect-prophetx-modal.d.ts +12 -0
- package/dist/types/pages/event-market/event-market.types.d.mts +5 -0
- package/dist/types/pages/event-market/event-market.types.d.ts +5 -0
- package/dist/types/pages/event-market/event-open-orders.d.mts +50 -0
- package/dist/types/pages/event-market/event-open-orders.d.ts +50 -0
- package/dist/types/pages/event-market/index.d.mts +3 -0
- package/dist/types/pages/event-market/index.d.ts +3 -0
- package/dist/types/pages/event-market/sports-event-market-page.d.mts +1 -1
- package/dist/types/pages/event-market/sports-event-market-page.d.ts +1 -1
- package/dist/types/pages/event-market/use-event-open-orders.d.mts +27 -0
- package/dist/types/pages/event-market/use-event-open-orders.d.ts +27 -0
- package/dist/types/pages/user-profile/components/available-balance-card.d.mts +2 -0
- package/dist/types/pages/user-profile/components/available-balance-card.d.ts +2 -0
- package/dist/types/pages/user-profile/components/betdex-account-activity.d.mts +4 -0
- package/dist/types/pages/user-profile/components/betdex-account-activity.d.ts +4 -0
- package/dist/types/pages/user-profile/components/betdex-account-card.d.mts +2 -0
- package/dist/types/pages/user-profile/components/betdex-account-card.d.ts +2 -0
- package/dist/types/pages/user-profile/components/betdex-account-transfers.d.mts +7 -0
- package/dist/types/pages/user-profile/components/betdex-account-transfers.d.ts +7 -0
- package/dist/types/pages/user-profile/components/open-order-row.d.mts +8 -1
- package/dist/types/pages/user-profile/components/open-order-row.d.ts +8 -1
- package/dist/types/pages/user-profile/user-profile.types.d.mts +5 -0
- package/dist/types/pages/user-profile/user-profile.types.d.ts +5 -0
- package/dist/types/primitives/chart/chart.constants.d.mts +7 -0
- package/dist/types/primitives/chart/chart.constants.d.ts +7 -0
- package/dist/types/primitives/chart/chart.types.d.mts +24 -2
- package/dist/types/primitives/chart/chart.types.d.ts +24 -2
- package/dist/types/primitives/chart/index.d.mts +2 -2
- package/dist/types/primitives/chart/index.d.ts +2 -2
- package/dist/types/primitives/chart/probability-chart.d.mts +22 -0
- package/dist/types/primitives/chart/probability-chart.d.ts +22 -0
- package/dist/types/primitives/chart/probability-chart.utils.d.mts +12 -0
- package/dist/types/primitives/chart/probability-chart.utils.d.ts +12 -0
- package/dist/types/primitives/chart/probability-live-tail.d.mts +16 -0
- package/dist/types/primitives/chart/probability-live-tail.d.ts +16 -0
- package/dist/types/primitives/remote-image/index.d.mts +1 -1
- package/dist/types/primitives/remote-image/index.d.ts +1 -1
- package/dist/types/primitives/remote-image/remote-image.types.d.mts +6 -0
- package/dist/types/primitives/remote-image/remote-image.types.d.ts +6 -0
- package/dist/types/primitives/skeleton/views/event-list-item-skeleton-view.d.mts +6 -0
- package/dist/types/primitives/skeleton/views/event-list-item-skeleton-view.d.ts +6 -0
- package/dist/types/primitives/venue-logo/svg/logo-betdex.d.mts +12 -0
- package/dist/types/primitives/venue-logo/svg/logo-betdex.d.ts +12 -0
- package/dist/types/primitives/venue-logo/svg/logo-tiprun.d.mts +7 -0
- package/dist/types/primitives/venue-logo/svg/logo-tiprun.d.ts +7 -0
- package/dist/types/shared/open-orders.d.mts +63 -0
- package/dist/types/shared/open-orders.d.ts +63 -0
- package/dist/types/shared/use-open-order-cancellation.d.mts +18 -0
- package/dist/types/shared/use-open-order-cancellation.d.ts +18 -0
- package/dist/types/trading/manage-betdex-account-modal.d.mts +5 -0
- package/dist/types/trading/manage-betdex-account-modal.d.ts +5 -0
- package/dist/types/trading/place-order/index.place-order.execution-steps.d.mts +2 -0
- package/dist/types/trading/place-order/index.place-order.execution-steps.d.ts +2 -0
- package/dist/types/trading/place-order/index.place-order.types.d.mts +5 -0
- package/dist/types/trading/place-order/index.place-order.types.d.ts +5 -0
- package/dist/types/trading/place-order/index.place-order.utils.d.mts +6 -1
- package/dist/types/trading/place-order/index.place-order.utils.d.ts +6 -1
- package/package.json +3 -3
|
@@ -0,0 +1,2040 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
isErrorWithStatus
|
|
4
|
+
} from "./chunk-2UPO6G3S.mjs";
|
|
5
|
+
import {
|
|
6
|
+
Badge,
|
|
7
|
+
Card,
|
|
8
|
+
CloseIcon,
|
|
9
|
+
Icon,
|
|
10
|
+
Modal,
|
|
11
|
+
RemoteImage,
|
|
12
|
+
SearchEmptyIcon,
|
|
13
|
+
Select,
|
|
14
|
+
Skeleton,
|
|
15
|
+
StateMessage,
|
|
16
|
+
Tabs,
|
|
17
|
+
Typography,
|
|
18
|
+
VenueLogo,
|
|
19
|
+
__objRest,
|
|
20
|
+
__spreadProps,
|
|
21
|
+
__spreadValues,
|
|
22
|
+
baseCardClassName,
|
|
23
|
+
cn,
|
|
24
|
+
dedupeVenueMarketsById,
|
|
25
|
+
filterEventsByTabValue,
|
|
26
|
+
formatMarketProbabilityPercent,
|
|
27
|
+
formatPriceGapPercent,
|
|
28
|
+
getMotionClassName,
|
|
29
|
+
mapEventToEventListItemEvent,
|
|
30
|
+
normalizeProbability,
|
|
31
|
+
resolveCategoryIdsFromPath,
|
|
32
|
+
resolveDisplayVolume,
|
|
33
|
+
resolveEventHeading,
|
|
34
|
+
resolveEventListItemEvent,
|
|
35
|
+
resolveOutcomeTitle,
|
|
36
|
+
resolveTabVenus,
|
|
37
|
+
resolveVenueLabel,
|
|
38
|
+
resolveYesOutcome,
|
|
39
|
+
sortCategoriesForNavigation,
|
|
40
|
+
sortOutcomes,
|
|
41
|
+
splitEventsByLifecycle,
|
|
42
|
+
validateSubcategoryPath
|
|
43
|
+
} from "./chunk-WIGSRHUG.mjs";
|
|
44
|
+
|
|
45
|
+
// src/events/item/index.tsx
|
|
46
|
+
import {
|
|
47
|
+
optimizedImageUrl,
|
|
48
|
+
retinaImageUrl,
|
|
49
|
+
resolveRecurringCryptoIdentity,
|
|
50
|
+
sortVenues,
|
|
51
|
+
useLabels,
|
|
52
|
+
useMidpoints,
|
|
53
|
+
useSdkUiConfig,
|
|
54
|
+
useVenueEvent,
|
|
55
|
+
useVenueMarketMidpoints,
|
|
56
|
+
useVenueMarkets
|
|
57
|
+
} from "@agg-build/hooks";
|
|
58
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
59
|
+
|
|
60
|
+
// src/events/item/event-list-item-v2.utils.ts
|
|
61
|
+
var isNonEmptyString = (value) => {
|
|
62
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
63
|
+
};
|
|
64
|
+
var getOutcomeSortPrice = (outcome) => {
|
|
65
|
+
var _a;
|
|
66
|
+
return (_a = normalizeProbability(outcome.price)) != null ? _a : -1;
|
|
67
|
+
};
|
|
68
|
+
var MAX_VISIBLE_OUTCOME_PRICE_PILLS = 3;
|
|
69
|
+
var resolveDisplayOutcome = (market) => {
|
|
70
|
+
var _a;
|
|
71
|
+
return (_a = resolveYesOutcome(market)) != null ? _a : [...market.venueMarketOutcomes].sort((left, right) => {
|
|
72
|
+
return getOutcomeSortPrice(right) - getOutcomeSortPrice(left);
|
|
73
|
+
})[0];
|
|
74
|
+
};
|
|
75
|
+
var resolveOutcomeRows = ({
|
|
76
|
+
venueMarkets,
|
|
77
|
+
marketCount
|
|
78
|
+
}) => {
|
|
79
|
+
if (venueMarkets.length === 0) return [];
|
|
80
|
+
if (marketCount === 1 && venueMarkets.length === 1) {
|
|
81
|
+
const [market] = venueMarkets;
|
|
82
|
+
return sortOutcomes(market.venueMarketOutcomes).map((outcome) => ({
|
|
83
|
+
id: outcome.id,
|
|
84
|
+
label: resolveOutcomeTitle(outcome),
|
|
85
|
+
market,
|
|
86
|
+
outcome
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
return venueMarkets.map((market) => {
|
|
90
|
+
const outcome = resolveDisplayOutcome(market);
|
|
91
|
+
if (!outcome) return void 0;
|
|
92
|
+
return {
|
|
93
|
+
id: market.id,
|
|
94
|
+
label: isNonEmptyString(market.question) ? market.question : resolveOutcomeTitle(outcome),
|
|
95
|
+
market,
|
|
96
|
+
outcome
|
|
97
|
+
};
|
|
98
|
+
}).filter((row) => row != null);
|
|
99
|
+
};
|
|
100
|
+
var collectOutcomePrices = (market, outcome, priceByOutcomeId) => {
|
|
101
|
+
var _a, _b, _c;
|
|
102
|
+
const prices = [];
|
|
103
|
+
const seenOutcomeKeys = /* @__PURE__ */ new Set();
|
|
104
|
+
const addPrice = (priceMarket, priceOutcome) => {
|
|
105
|
+
if (!priceMarket || !priceOutcome) return;
|
|
106
|
+
const resolvedPrice = priceByOutcomeId === void 0 ? priceOutcome.price : priceByOutcomeId.has(priceOutcome.id) ? priceByOutcomeId.get(priceOutcome.id) : void 0;
|
|
107
|
+
const normalizedPrice = normalizeProbability(resolvedPrice);
|
|
108
|
+
if (normalizedPrice == null) return;
|
|
109
|
+
const key = `${priceMarket.id}:${priceOutcome.id}`;
|
|
110
|
+
if (seenOutcomeKeys.has(key)) return;
|
|
111
|
+
seenOutcomeKeys.add(key);
|
|
112
|
+
prices.push({
|
|
113
|
+
venue: priceMarket.venue,
|
|
114
|
+
market: priceMarket,
|
|
115
|
+
outcome: priceOutcome,
|
|
116
|
+
price: normalizedPrice,
|
|
117
|
+
isBest: false
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
addPrice(market, outcome);
|
|
121
|
+
for (const matchedOutcomeRef of (_a = outcome.matchedVenueMarketOutcomes) != null ? _a : []) {
|
|
122
|
+
const matchedMarket = (_b = market.matchedVenueMarkets) == null ? void 0 : _b.find((candidate) => {
|
|
123
|
+
return candidate.id === matchedOutcomeRef.venueMarketId;
|
|
124
|
+
});
|
|
125
|
+
const matchedOutcome = (_c = matchedMarket == null ? void 0 : matchedMarket.venueMarketOutcomes) == null ? void 0 : _c.find((candidate) => {
|
|
126
|
+
return candidate.id === matchedOutcomeRef.venueMarketOutcomeId;
|
|
127
|
+
});
|
|
128
|
+
addPrice(matchedMarket, matchedOutcome);
|
|
129
|
+
}
|
|
130
|
+
if (prices.length === 0) return [];
|
|
131
|
+
const bestPriceByVenue = /* @__PURE__ */ new Map();
|
|
132
|
+
for (const price of prices) {
|
|
133
|
+
const existing = bestPriceByVenue.get(price.venue);
|
|
134
|
+
if (!existing || price.price < existing.price) {
|
|
135
|
+
bestPriceByVenue.set(price.venue, price);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const dedupedPrices = Array.from(bestPriceByVenue.values());
|
|
139
|
+
const sortedPricesByBestOdds = [...dedupedPrices].sort((left, right) => {
|
|
140
|
+
return left.price - right.price;
|
|
141
|
+
});
|
|
142
|
+
const bestPrice = sortedPricesByBestOdds[0];
|
|
143
|
+
if (!bestPrice) return [];
|
|
144
|
+
const visiblePrices = [
|
|
145
|
+
sortedPricesByBestOdds.at(-1),
|
|
146
|
+
sortedPricesByBestOdds[1],
|
|
147
|
+
bestPrice
|
|
148
|
+
].reduce((accumulator, price) => {
|
|
149
|
+
if (!price) return accumulator;
|
|
150
|
+
const isDuplicate = accumulator.some((candidate) => {
|
|
151
|
+
return candidate.market.id === price.market.id && candidate.outcome.id === price.outcome.id;
|
|
152
|
+
});
|
|
153
|
+
if (isDuplicate) return accumulator;
|
|
154
|
+
accumulator.push(price);
|
|
155
|
+
return accumulator;
|
|
156
|
+
}, []);
|
|
157
|
+
return visiblePrices.slice(0, MAX_VISIBLE_OUTCOME_PRICE_PILLS).map((price) => __spreadProps(__spreadValues({}, price), {
|
|
158
|
+
isBest: price.market.id === bestPrice.market.id && price.outcome.id === bestPrice.outcome.id
|
|
159
|
+
}));
|
|
160
|
+
};
|
|
161
|
+
var collectMatchedVenues = (rows) => {
|
|
162
|
+
const venues = /* @__PURE__ */ new Set();
|
|
163
|
+
for (const row of rows) {
|
|
164
|
+
if (row.prices.length < 2) continue;
|
|
165
|
+
for (const price of row.prices) {
|
|
166
|
+
venues.add(price.venue);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return Array.from(venues);
|
|
170
|
+
};
|
|
171
|
+
var computePriceGapsFromComparisonRows = (rows) => {
|
|
172
|
+
const gapsByVenueMarketId = /* @__PURE__ */ new Map();
|
|
173
|
+
for (const row of rows) {
|
|
174
|
+
if (row.prices.length < 2) continue;
|
|
175
|
+
const prices = row.prices.map((price) => price.price);
|
|
176
|
+
const minPrice = Math.min(...prices);
|
|
177
|
+
const maxPrice = Math.max(...prices);
|
|
178
|
+
if (minPrice <= 0 || maxPrice <= minPrice) continue;
|
|
179
|
+
gapsByVenueMarketId.set(row.market.id, (maxPrice - minPrice) * 100);
|
|
180
|
+
}
|
|
181
|
+
return gapsByVenueMarketId;
|
|
182
|
+
};
|
|
183
|
+
var normalizeEventListItemV2Comparison = ({
|
|
184
|
+
venueMarkets,
|
|
185
|
+
marketCount,
|
|
186
|
+
priceByOutcomeId
|
|
187
|
+
}) => {
|
|
188
|
+
const outcomeRows = resolveOutcomeRows({ venueMarkets, marketCount });
|
|
189
|
+
const rows = outcomeRows.map((row) => {
|
|
190
|
+
const prices = collectOutcomePrices(row.market, row.outcome, priceByOutcomeId);
|
|
191
|
+
return __spreadProps(__spreadValues({}, row), {
|
|
192
|
+
prices
|
|
193
|
+
});
|
|
194
|
+
}).filter((row) => row.prices.length === 0 || row.prices.some((price) => price.price > 0));
|
|
195
|
+
const matchedVenues = collectMatchedVenues(rows);
|
|
196
|
+
return {
|
|
197
|
+
rows,
|
|
198
|
+
matchedVenues,
|
|
199
|
+
hasVenueCompetition: matchedVenues.length > 1
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// src/events/item/index.tsx
|
|
204
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
205
|
+
var EventListItemLoadingState = ({
|
|
206
|
+
classNames,
|
|
207
|
+
ariaLabel
|
|
208
|
+
}) => {
|
|
209
|
+
const labels = useLabels();
|
|
210
|
+
return /* @__PURE__ */ jsx(
|
|
211
|
+
Skeleton,
|
|
212
|
+
{
|
|
213
|
+
view: "event-list-item",
|
|
214
|
+
className: classNames == null ? void 0 : classNames.root,
|
|
215
|
+
ariaLabel: ariaLabel != null ? ariaLabel : labels.eventItem.loading
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
};
|
|
219
|
+
var EventListItemUnavailableState = ({
|
|
220
|
+
classNames,
|
|
221
|
+
ariaLabel
|
|
222
|
+
}) => {
|
|
223
|
+
const labels = useLabels();
|
|
224
|
+
return /* @__PURE__ */ jsx(
|
|
225
|
+
Card,
|
|
226
|
+
{
|
|
227
|
+
className: cn(
|
|
228
|
+
"group/agg-event-card agg-event-card-unavailable",
|
|
229
|
+
baseCardClassName,
|
|
230
|
+
classNames == null ? void 0 : classNames.root
|
|
231
|
+
),
|
|
232
|
+
role: "status",
|
|
233
|
+
"aria-label": ariaLabel != null ? ariaLabel : labels.eventItem.unavailableAria,
|
|
234
|
+
children: /* @__PURE__ */ jsxs("div", { className: cn("agg-event-card-header min-h-12 flex flex-col gap-1", classNames == null ? void 0 : classNames.header), children: [
|
|
235
|
+
/* @__PURE__ */ jsx(
|
|
236
|
+
Typography,
|
|
237
|
+
{
|
|
238
|
+
variant: "body-large-strong",
|
|
239
|
+
className: cn("agg-event-title truncate", classNames == null ? void 0 : classNames.title),
|
|
240
|
+
children: labels.eventItem.unavailableTitle
|
|
241
|
+
}
|
|
242
|
+
),
|
|
243
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-agg-muted-foreground", children: labels.eventItem.unavailableDescription })
|
|
244
|
+
] })
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
};
|
|
248
|
+
var EventListItemNotFoundState = ({
|
|
249
|
+
classNames: _classNames,
|
|
250
|
+
ariaLabel: _ariaLabel
|
|
251
|
+
}) => {
|
|
252
|
+
const labels = useLabels();
|
|
253
|
+
return /* @__PURE__ */ jsx(
|
|
254
|
+
StateMessage,
|
|
255
|
+
{
|
|
256
|
+
title: labels.eventItemDetails.notFoundTitle,
|
|
257
|
+
description: labels.eventItemDetails.notFoundDescription,
|
|
258
|
+
icon: /* @__PURE__ */ jsx(SearchEmptyIcon, {}),
|
|
259
|
+
classNames: { root: "agg-event-card-state min-h-[280px] md:min-h-[320px]" }
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
};
|
|
263
|
+
var OUTCOMES_SCROLL_LOAD_THRESHOLD_PX = 16;
|
|
264
|
+
var OUTCOMES_SCROLL_STATE_EPSILON_PX = 1;
|
|
265
|
+
var OUTCOMES_SCROLL_MASK_HEIGHT_PX = 24;
|
|
266
|
+
var MARKET_ID_QUERY_PARAM = "marketId";
|
|
267
|
+
var OUTCOME_ID_QUERY_PARAM = "outcomeId";
|
|
268
|
+
var OUTCOME_ROW_SELECTOR = ".agg-outcome-row";
|
|
269
|
+
var DEFAULT_OUTCOMES_SCROLL_STATE = {
|
|
270
|
+
hasOverflow: false,
|
|
271
|
+
isAtTop: true,
|
|
272
|
+
isAtBottom: true,
|
|
273
|
+
remainingMarkets: 0
|
|
274
|
+
};
|
|
275
|
+
var areOutcomesScrollStatesEqual = (left, right) => {
|
|
276
|
+
return left.hasOverflow === right.hasOverflow && left.isAtTop === right.isAtTop && left.isAtBottom === right.isAtBottom && left.remainingMarkets === right.remainingMarkets;
|
|
277
|
+
};
|
|
278
|
+
var useOutcomesScrollState = ({
|
|
279
|
+
totalMarketCount,
|
|
280
|
+
onReachScrollThreshold
|
|
281
|
+
}) => {
|
|
282
|
+
const containerRef = useRef(null);
|
|
283
|
+
const frameRef = useRef(null);
|
|
284
|
+
const scrollStateRef = useRef(DEFAULT_OUTCOMES_SCROLL_STATE);
|
|
285
|
+
const [scrollState, setScrollState] = useState(
|
|
286
|
+
DEFAULT_OUTCOMES_SCROLL_STATE
|
|
287
|
+
);
|
|
288
|
+
const measureScrollState = useCallback(() => {
|
|
289
|
+
frameRef.current = null;
|
|
290
|
+
const element = containerRef.current;
|
|
291
|
+
if (!element) return;
|
|
292
|
+
const { clientHeight, scrollHeight, scrollTop } = element;
|
|
293
|
+
const hasOverflow = scrollHeight > clientHeight + OUTCOMES_SCROLL_STATE_EPSILON_PX;
|
|
294
|
+
const isAtTop = scrollTop <= OUTCOMES_SCROLL_STATE_EPSILON_PX;
|
|
295
|
+
const isAtBottom = !hasOverflow || scrollTop + clientHeight >= scrollHeight - OUTCOMES_SCROLL_STATE_EPSILON_PX;
|
|
296
|
+
const loadedRows = Array.from(element.querySelectorAll(OUTCOME_ROW_SELECTOR));
|
|
297
|
+
const visibleMarketCount = loadedRows.reduce((count, row) => {
|
|
298
|
+
return count + (row.offsetTop < clientHeight - OUTCOMES_SCROLL_STATE_EPSILON_PX ? 1 : 0);
|
|
299
|
+
}, 0);
|
|
300
|
+
const remainingMarkets = hasOverflow ? Math.max(0, totalMarketCount - visibleMarketCount) : 0;
|
|
301
|
+
const nextScrollState = {
|
|
302
|
+
hasOverflow,
|
|
303
|
+
isAtTop,
|
|
304
|
+
isAtBottom,
|
|
305
|
+
remainingMarkets
|
|
306
|
+
};
|
|
307
|
+
if (!areOutcomesScrollStatesEqual(scrollStateRef.current, nextScrollState)) {
|
|
308
|
+
scrollStateRef.current = nextScrollState;
|
|
309
|
+
setScrollState(nextScrollState);
|
|
310
|
+
}
|
|
311
|
+
const distanceToBottom = scrollHeight - scrollTop - clientHeight;
|
|
312
|
+
if (distanceToBottom <= OUTCOMES_SCROLL_LOAD_THRESHOLD_PX) {
|
|
313
|
+
onReachScrollThreshold == null ? void 0 : onReachScrollThreshold();
|
|
314
|
+
}
|
|
315
|
+
}, [onReachScrollThreshold, totalMarketCount]);
|
|
316
|
+
const updateScrollState = useCallback(() => {
|
|
317
|
+
if (frameRef.current != null) return;
|
|
318
|
+
frameRef.current = window.requestAnimationFrame(measureScrollState);
|
|
319
|
+
}, [measureScrollState]);
|
|
320
|
+
useEffect(() => {
|
|
321
|
+
const element = containerRef.current;
|
|
322
|
+
if (!element) return;
|
|
323
|
+
element.addEventListener("scroll", updateScrollState, { passive: true });
|
|
324
|
+
let resizeObserver = null;
|
|
325
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
326
|
+
resizeObserver = new ResizeObserver(() => {
|
|
327
|
+
updateScrollState();
|
|
328
|
+
});
|
|
329
|
+
resizeObserver.observe(element);
|
|
330
|
+
}
|
|
331
|
+
updateScrollState();
|
|
332
|
+
return () => {
|
|
333
|
+
element.removeEventListener("scroll", updateScrollState);
|
|
334
|
+
resizeObserver == null ? void 0 : resizeObserver.disconnect();
|
|
335
|
+
if (frameRef.current != null) {
|
|
336
|
+
window.cancelAnimationFrame(frameRef.current);
|
|
337
|
+
frameRef.current = null;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
}, [updateScrollState]);
|
|
341
|
+
return { containerRef, scrollState, updateScrollState };
|
|
342
|
+
};
|
|
343
|
+
var buildOutcomeMidpointsByOutcomeId = (midpointRows) => {
|
|
344
|
+
const outcomeMidpointsByOutcomeId = /* @__PURE__ */ new Map();
|
|
345
|
+
const addOutcomeMidpoints = (value) => {
|
|
346
|
+
var _a, _b;
|
|
347
|
+
if (!value || typeof value !== "object") return;
|
|
348
|
+
const row = value;
|
|
349
|
+
for (const outcome of (_a = row.outcomes) != null ? _a : []) {
|
|
350
|
+
if (outcome.midpoint == null) continue;
|
|
351
|
+
outcomeMidpointsByOutcomeId.set(outcome.venueMarketOutcomeId, outcome.midpoint);
|
|
352
|
+
}
|
|
353
|
+
for (const matchedRow of (_b = row.matched) != null ? _b : []) {
|
|
354
|
+
addOutcomeMidpoints(matchedRow);
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
for (const row of midpointRows) {
|
|
358
|
+
addOutcomeMidpoints(row);
|
|
359
|
+
}
|
|
360
|
+
return outcomeMidpointsByOutcomeId;
|
|
361
|
+
};
|
|
362
|
+
var buildArbReturnByVenueMarketId = (midpointRows) => {
|
|
363
|
+
const arbReturnByVenueMarketId = /* @__PURE__ */ new Map();
|
|
364
|
+
const addArbReturn = (value) => {
|
|
365
|
+
var _a, _b;
|
|
366
|
+
if (!value || typeof value !== "object") return;
|
|
367
|
+
const row = value;
|
|
368
|
+
if (row.venueMarketId && !arbReturnByVenueMarketId.has(row.venueMarketId)) {
|
|
369
|
+
arbReturnByVenueMarketId.set(row.venueMarketId, (_a = row.arbReturn) != null ? _a : null);
|
|
370
|
+
}
|
|
371
|
+
for (const matchedRow of (_b = row.matched) != null ? _b : []) {
|
|
372
|
+
addArbReturn(matchedRow);
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
for (const row of midpointRows) {
|
|
376
|
+
addArbReturn(row);
|
|
377
|
+
}
|
|
378
|
+
return arbReturnByVenueMarketId;
|
|
379
|
+
};
|
|
380
|
+
var resolveMarketHrefFromEventHref = (eventHref, marketId, outcomeId) => {
|
|
381
|
+
if (!eventHref) return void 0;
|
|
382
|
+
if (typeof window === "undefined") return void 0;
|
|
383
|
+
try {
|
|
384
|
+
const url = new URL(eventHref, window.location.origin);
|
|
385
|
+
url.searchParams.set(MARKET_ID_QUERY_PARAM, marketId);
|
|
386
|
+
url.searchParams.set(OUTCOME_ID_QUERY_PARAM, outcomeId);
|
|
387
|
+
return url.toString();
|
|
388
|
+
} catch (e) {
|
|
389
|
+
return void 0;
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
var EventListItemContent = ({
|
|
393
|
+
event,
|
|
394
|
+
classNames,
|
|
395
|
+
arbitrageByOutcomeId,
|
|
396
|
+
midpointPrices,
|
|
397
|
+
midpointRows: sharedMidpointRows,
|
|
398
|
+
midpointsLoading,
|
|
399
|
+
onEventClick,
|
|
400
|
+
onMarketClick,
|
|
401
|
+
getMarketHref,
|
|
402
|
+
href,
|
|
403
|
+
ariaLabel,
|
|
404
|
+
marketStatus
|
|
405
|
+
}) => {
|
|
406
|
+
var _a;
|
|
407
|
+
const config = useSdkUiConfig();
|
|
408
|
+
const labels = useLabels();
|
|
409
|
+
const allVenueMarkets = useMemo(() => event.venueMarkets, [event.venueMarkets]);
|
|
410
|
+
const recurringCryptoIdentity = resolveRecurringCryptoIdentity(event);
|
|
411
|
+
const eventHeading = resolveEventHeading({
|
|
412
|
+
title: event.title,
|
|
413
|
+
categories: event.categories,
|
|
414
|
+
structureType: event.structureType,
|
|
415
|
+
gameStartTime: event.gameStartTime,
|
|
416
|
+
endDate: event.endDate,
|
|
417
|
+
venueMarkets: event.venueMarkets,
|
|
418
|
+
recurringCryptoWindowStart: recurringCryptoIdentity == null ? void 0 : recurringCryptoIdentity.windowStart,
|
|
419
|
+
recurringCryptoDuration: recurringCryptoIdentity == null ? void 0 : recurringCryptoIdentity.duration
|
|
420
|
+
});
|
|
421
|
+
const resolvedTitle = eventHeading.title;
|
|
422
|
+
const resolvedTimestamp = eventHeading.timestampLabel;
|
|
423
|
+
const resolvedImage = event.image;
|
|
424
|
+
const visibleVenueLogos = useMemo(() => {
|
|
425
|
+
var _a2;
|
|
426
|
+
return sortVenues(Array.from(new Set(((_a2 = event.venues) != null ? _a2 : []).map((venue) => venue))));
|
|
427
|
+
}, [event.venues]);
|
|
428
|
+
const resolvedMarketCount = typeof event.marketCount === "number" && Number.isFinite(event.marketCount) ? Math.max(0, Math.floor(event.marketCount)) : allVenueMarkets.length;
|
|
429
|
+
const resolvedVenueCount = typeof event.venueCount === "number" && Number.isFinite(event.venueCount) ? Math.max(0, Math.floor(event.venueCount)) : visibleVenueLogos.length;
|
|
430
|
+
const [isLazyMarketsQueryEnabled, setIsLazyMarketsQueryEnabled] = useState(false);
|
|
431
|
+
const shouldEnableLazyMarketLoading = useMemo(() => {
|
|
432
|
+
if (!event.id) return false;
|
|
433
|
+
const hasExplicitMarketCount = typeof event.marketCount === "number" && Number.isFinite(event.marketCount);
|
|
434
|
+
if (hasExplicitMarketCount) {
|
|
435
|
+
return resolvedMarketCount > allVenueMarkets.length;
|
|
436
|
+
}
|
|
437
|
+
return allVenueMarkets.length > 1;
|
|
438
|
+
}, [allVenueMarkets.length, event.id, event.marketCount, resolvedMarketCount]);
|
|
439
|
+
const {
|
|
440
|
+
markets: lazyLoadedMarkets,
|
|
441
|
+
fetchNextPage: fetchNextLazyMarketsPage,
|
|
442
|
+
hasNextPage: hasNextLazyMarketsPage,
|
|
443
|
+
isLoading: isLoadingLazyMarkets,
|
|
444
|
+
isFetchingNextPage: isFetchingNextLazyMarketsPage
|
|
445
|
+
} = useVenueMarkets({
|
|
446
|
+
venueEventId: event.id,
|
|
447
|
+
enabled: shouldEnableLazyMarketLoading && isLazyMarketsQueryEnabled,
|
|
448
|
+
// List/tile surface: axis/dates sort by volume so the scroll tail matches
|
|
449
|
+
// the volume-sorted top-3 (the detail page omits context and keeps the
|
|
450
|
+
// structured threshold/date order).
|
|
451
|
+
context: "list",
|
|
452
|
+
status: marketStatus
|
|
453
|
+
});
|
|
454
|
+
const resolvedOutcomeMarkets = useMemo(() => {
|
|
455
|
+
if (!isLazyMarketsQueryEnabled || lazyLoadedMarkets.length === 0) return allVenueMarkets;
|
|
456
|
+
return dedupeVenueMarketsById([...allVenueMarkets, ...lazyLoadedMarkets]);
|
|
457
|
+
}, [allVenueMarkets, isLazyMarketsQueryEnabled, lazyLoadedMarkets]);
|
|
458
|
+
const hasExpandedMarkets = isLazyMarketsQueryEnabled && lazyLoadedMarkets.length > 0;
|
|
459
|
+
const shouldUseSharedMidpoints = !hasExpandedMarkets && (midpointPrices !== void 0 || sharedMidpointRows !== void 0 || midpointsLoading !== void 0);
|
|
460
|
+
const midpointVenueMarketIds = useMemo(() => {
|
|
461
|
+
var _a2;
|
|
462
|
+
const ids = [];
|
|
463
|
+
for (const market of resolvedOutcomeMarkets) {
|
|
464
|
+
ids.push(market.id);
|
|
465
|
+
for (const sibling of (_a2 = market.matchedVenueMarkets) != null ? _a2 : []) {
|
|
466
|
+
ids.push(sibling.id);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return [...new Set(ids)];
|
|
470
|
+
}, [resolvedOutcomeMarkets]);
|
|
471
|
+
const { midpointRows: fetchedMidpointRows, isLoading: isVenueMarketMidpointsLoading } = useVenueMarketMidpoints({
|
|
472
|
+
venueMarketIds: shouldUseSharedMidpoints ? [] : midpointVenueMarketIds,
|
|
473
|
+
enabled: !shouldUseSharedMidpoints && midpointVenueMarketIds.length > 0
|
|
474
|
+
});
|
|
475
|
+
const { prices: displayMidpointsByOutcomeId, isLoading: isOutcomeMidpointsLoading } = useMidpoints(shouldUseSharedMidpoints ? [] : resolvedOutcomeMarkets);
|
|
476
|
+
const resolvedMidpointRows = useMemo(
|
|
477
|
+
() => shouldUseSharedMidpoints ? sharedMidpointRows != null ? sharedMidpointRows : [] : fetchedMidpointRows,
|
|
478
|
+
[fetchedMidpointRows, sharedMidpointRows, shouldUseSharedMidpoints]
|
|
479
|
+
);
|
|
480
|
+
const resolvedDisplayMidpointsByOutcomeId = useMemo(
|
|
481
|
+
() => shouldUseSharedMidpoints ? midpointPrices != null ? midpointPrices : /* @__PURE__ */ new Map() : displayMidpointsByOutcomeId,
|
|
482
|
+
[displayMidpointsByOutcomeId, midpointPrices, shouldUseSharedMidpoints]
|
|
483
|
+
);
|
|
484
|
+
const isAwaitingMidpoints = midpointsLoading != null ? midpointsLoading : isOutcomeMidpointsLoading || midpointVenueMarketIds.length > 0 && isVenueMarketMidpointsLoading;
|
|
485
|
+
const displayPriceByOutcomeId = useMemo(() => {
|
|
486
|
+
const priceByOutcomeId = new Map(resolvedDisplayMidpointsByOutcomeId);
|
|
487
|
+
for (const [outcomeId, price] of buildOutcomeMidpointsByOutcomeId(resolvedMidpointRows)) {
|
|
488
|
+
priceByOutcomeId.set(outcomeId, price);
|
|
489
|
+
}
|
|
490
|
+
return priceByOutcomeId;
|
|
491
|
+
}, [resolvedDisplayMidpointsByOutcomeId, resolvedMidpointRows]);
|
|
492
|
+
const comparison = useMemo(() => {
|
|
493
|
+
return normalizeEventListItemV2Comparison({
|
|
494
|
+
venueMarkets: resolvedOutcomeMarkets,
|
|
495
|
+
marketCount: resolvedMarketCount,
|
|
496
|
+
priceByOutcomeId: displayPriceByOutcomeId
|
|
497
|
+
});
|
|
498
|
+
}, [displayPriceByOutcomeId, resolvedMarketCount, resolvedOutcomeMarkets]);
|
|
499
|
+
const gapsByVenueMarketId = useMemo(() => {
|
|
500
|
+
return computePriceGapsFromComparisonRows(comparison.rows);
|
|
501
|
+
}, [comparison.rows]);
|
|
502
|
+
const arbReturnByVenueMarketId = useMemo(() => {
|
|
503
|
+
return buildArbReturnByVenueMarketId(resolvedMidpointRows);
|
|
504
|
+
}, [resolvedMidpointRows]);
|
|
505
|
+
const shouldRenderLoadingOutcomeRow = shouldEnableLazyMarketLoading && (!isLazyMarketsQueryEnabled || isLoadingLazyMarkets || isFetchingNextLazyMarketsPage || hasNextLazyMarketsPage);
|
|
506
|
+
const resolvedVolume = (_a = resolveDisplayVolume(event.volume, allVenueMarkets)) != null ? _a : 0;
|
|
507
|
+
const volumeLabel = `${config.formatting.formatCompactCurrency(resolvedVolume)} ${labels.eventItem.volumeSuffix}`;
|
|
508
|
+
const orderedFooterVenues = useMemo(() => {
|
|
509
|
+
const venues = visibleVenueLogos.length > 0 ? visibleVenueLogos : comparison.matchedVenues.length > 0 ? comparison.matchedVenues : event.venue ? [event.venue] : [];
|
|
510
|
+
return Array.from(new Set(venues));
|
|
511
|
+
}, [comparison.matchedVenues, event.venue, visibleVenueLogos]);
|
|
512
|
+
const shouldShowMatchedVenueSummary = resolvedVenueCount > 1 || orderedFooterVenues.length > 1;
|
|
513
|
+
const visibleFooterVenues = shouldShowMatchedVenueSummary ? orderedFooterVenues : orderedFooterVenues.slice(0, 1);
|
|
514
|
+
const singleFooterVenue = shouldShowMatchedVenueSummary ? void 0 : visibleFooterVenues[0];
|
|
515
|
+
const matchedCountLabel = labels.eventItem.matchedCount(
|
|
516
|
+
Math.max(resolvedVenueCount, visibleFooterVenues.length)
|
|
517
|
+
);
|
|
518
|
+
const handleOutcomesScrollThreshold = useCallback(() => {
|
|
519
|
+
if (!shouldEnableLazyMarketLoading) return;
|
|
520
|
+
if (!isLazyMarketsQueryEnabled) {
|
|
521
|
+
setIsLazyMarketsQueryEnabled(true);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
if (!hasNextLazyMarketsPage) return;
|
|
525
|
+
if (isLoadingLazyMarkets || isFetchingNextLazyMarketsPage) return;
|
|
526
|
+
void fetchNextLazyMarketsPage();
|
|
527
|
+
}, [
|
|
528
|
+
fetchNextLazyMarketsPage,
|
|
529
|
+
hasNextLazyMarketsPage,
|
|
530
|
+
isFetchingNextLazyMarketsPage,
|
|
531
|
+
isLazyMarketsQueryEnabled,
|
|
532
|
+
isLoadingLazyMarkets,
|
|
533
|
+
shouldEnableLazyMarketLoading
|
|
534
|
+
]);
|
|
535
|
+
const {
|
|
536
|
+
containerRef: outcomesContainerRef,
|
|
537
|
+
scrollState: outcomesScrollState,
|
|
538
|
+
updateScrollState
|
|
539
|
+
} = useOutcomesScrollState({
|
|
540
|
+
totalMarketCount: resolvedMarketCount,
|
|
541
|
+
onReachScrollThreshold: handleOutcomesScrollThreshold
|
|
542
|
+
});
|
|
543
|
+
const shouldUseNativeLinkNavigation = (eventToHandle) => {
|
|
544
|
+
return eventToHandle.metaKey || eventToHandle.ctrlKey || eventToHandle.shiftKey || eventToHandle.altKey || eventToHandle.button === 1;
|
|
545
|
+
};
|
|
546
|
+
const handleClick = (eventToHandle) => {
|
|
547
|
+
if (!eventToHandle) {
|
|
548
|
+
onEventClick == null ? void 0 : onEventClick(event);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
if (!href) {
|
|
552
|
+
onEventClick == null ? void 0 : onEventClick(event);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
if (shouldUseNativeLinkNavigation(eventToHandle)) {
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
if (!onEventClick) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
eventToHandle.preventDefault();
|
|
562
|
+
eventToHandle.stopPropagation();
|
|
563
|
+
onEventClick(event);
|
|
564
|
+
};
|
|
565
|
+
const handleOutcomeBadgeClick = (eventToHandle, market, outcome, marketHref) => {
|
|
566
|
+
eventToHandle.preventDefault();
|
|
567
|
+
eventToHandle.stopPropagation();
|
|
568
|
+
if (marketHref && shouldUseNativeLinkNavigation(eventToHandle)) {
|
|
569
|
+
window.open(marketHref, "_blank", "noopener,noreferrer");
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
if (onMarketClick) {
|
|
573
|
+
onMarketClick(event, market, outcome);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
if (marketHref) {
|
|
577
|
+
window.location.assign(marketHref);
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
const handleKeyDown = (eventToHandle) => {
|
|
581
|
+
if (href) {
|
|
582
|
+
if ((eventToHandle == null ? void 0 : eventToHandle.key) === " ") {
|
|
583
|
+
eventToHandle == null ? void 0 : eventToHandle.preventDefault();
|
|
584
|
+
eventToHandle.currentTarget.click();
|
|
585
|
+
}
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
if (!onEventClick) return;
|
|
589
|
+
if ((eventToHandle == null ? void 0 : eventToHandle.key) === "Enter" || (eventToHandle == null ? void 0 : eventToHandle.key) === " ") {
|
|
590
|
+
eventToHandle == null ? void 0 : eventToHandle.preventDefault();
|
|
591
|
+
onEventClick == null ? void 0 : onEventClick(event);
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
useEffect(() => {
|
|
595
|
+
updateScrollState();
|
|
596
|
+
}, [comparison.rows.length, shouldRenderLoadingOutcomeRow, updateScrollState]);
|
|
597
|
+
const renderArbitrage = (value) => {
|
|
598
|
+
if (value == null) return null;
|
|
599
|
+
if (Math.abs(value) < config.market.arbitrageThreshold) return null;
|
|
600
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-1", "text-agg-success"), children: [
|
|
601
|
+
/* @__PURE__ */ jsx(Typography, { variant: "label-strong", className: "text-agg-success", children: config.formatting.formatPercent(value) }),
|
|
602
|
+
/* @__PURE__ */ jsx(
|
|
603
|
+
Icon,
|
|
604
|
+
{
|
|
605
|
+
name: "triangle-up",
|
|
606
|
+
size: "small",
|
|
607
|
+
title: labels.eventItem.arbitrage,
|
|
608
|
+
className: "size-2!"
|
|
609
|
+
}
|
|
610
|
+
)
|
|
611
|
+
] });
|
|
612
|
+
};
|
|
613
|
+
const renderPriceStripSkeleton = (count) => {
|
|
614
|
+
const safeCount = Math.max(1, Math.min(count || 1, 3));
|
|
615
|
+
const collapsedCount = safeCount - 1;
|
|
616
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
617
|
+
Array.from({ length: collapsedCount }).map((_, index) => /* @__PURE__ */ jsx(
|
|
618
|
+
"span",
|
|
619
|
+
{
|
|
620
|
+
"aria-hidden": "true",
|
|
621
|
+
className: cn(
|
|
622
|
+
"agg-outcome-price-loading agg-outcome-price-loading-collapsed",
|
|
623
|
+
"h-[30px] w-[30px] shrink-0 rounded-agg-full bg-agg-separator animate-pulse",
|
|
624
|
+
index > 0 && "-ml-3"
|
|
625
|
+
)
|
|
626
|
+
},
|
|
627
|
+
`agg-outcome-price-loading-collapsed-${index}`
|
|
628
|
+
)),
|
|
629
|
+
/* @__PURE__ */ jsx(
|
|
630
|
+
"span",
|
|
631
|
+
{
|
|
632
|
+
"aria-hidden": "true",
|
|
633
|
+
className: cn(
|
|
634
|
+
"agg-outcome-price-loading agg-outcome-price-loading-best",
|
|
635
|
+
"h-[30px] w-[68px] shrink-0 rounded-agg-full bg-agg-separator animate-pulse",
|
|
636
|
+
collapsedCount > 0 && "ml-2"
|
|
637
|
+
)
|
|
638
|
+
}
|
|
639
|
+
)
|
|
640
|
+
] });
|
|
641
|
+
};
|
|
642
|
+
const renderPriceGapPill = (value, source = "percent") => {
|
|
643
|
+
if (!config.features.enablePriceGap) return null;
|
|
644
|
+
if (isAwaitingMidpoints) return null;
|
|
645
|
+
const formattedPriceGap = formatPriceGapPercent(value, source);
|
|
646
|
+
if (!formattedPriceGap) return null;
|
|
647
|
+
return /* @__PURE__ */ jsxs(
|
|
648
|
+
"span",
|
|
649
|
+
{
|
|
650
|
+
className: cn(
|
|
651
|
+
"agg-price-gap-pill",
|
|
652
|
+
"inline-flex max-w-[52px] shrink-0 items-center gap-1 overflow-hidden whitespace-nowrap",
|
|
653
|
+
"text-agg-2xs font-agg-bold leading-agg-14 text-agg-success",
|
|
654
|
+
"opacity-100 transition-all duration-200 ease-out",
|
|
655
|
+
"group-hover/agg-event-card:mr-0 group-hover/agg-event-card:max-w-0 group-hover/agg-event-card:opacity-0"
|
|
656
|
+
),
|
|
657
|
+
title: labels.eventItem.priceGap,
|
|
658
|
+
"aria-label": `${formattedPriceGap} ${labels.eventItem.priceGap}`,
|
|
659
|
+
children: [
|
|
660
|
+
/* @__PURE__ */ jsx(
|
|
661
|
+
"i",
|
|
662
|
+
{
|
|
663
|
+
"aria-hidden": "true",
|
|
664
|
+
className: "fi-rr-arrow-down inline-flex size-3! shrink-0 items-center justify-center text-agg-xs text-agg-success"
|
|
665
|
+
}
|
|
666
|
+
),
|
|
667
|
+
/* @__PURE__ */ jsx("span", { children: formattedPriceGap })
|
|
668
|
+
]
|
|
669
|
+
}
|
|
670
|
+
);
|
|
671
|
+
};
|
|
672
|
+
const renderComparisonPriceBadge = (row, price, priceIndex) => {
|
|
673
|
+
var _a2;
|
|
674
|
+
const marketHref = (_a2 = getMarketHref == null ? void 0 : getMarketHref(event, row.market, row.outcome)) != null ? _a2 : resolveMarketHrefFromEventHref(href, row.market.id, row.outcome.id);
|
|
675
|
+
const isInteractive = Boolean(onMarketClick || marketHref);
|
|
676
|
+
const hasVenueCompetition = row.prices.length > 1;
|
|
677
|
+
const isHighlightedBestPrice = hasVenueCompetition && price.isBest;
|
|
678
|
+
const shouldCollapsePriceText = hasVenueCompetition && !isHighlightedBestPrice;
|
|
679
|
+
return /* @__PURE__ */ jsx(
|
|
680
|
+
Badge,
|
|
681
|
+
{
|
|
682
|
+
text: formatMarketProbabilityPercent(price.price, config.formatting.formatPercent),
|
|
683
|
+
prefix: /* @__PURE__ */ jsx(
|
|
684
|
+
VenueLogo,
|
|
685
|
+
{
|
|
686
|
+
venue: price.venue,
|
|
687
|
+
size: "small",
|
|
688
|
+
isMonochromatic: !isHighlightedBestPrice,
|
|
689
|
+
className: cn(!isHighlightedBestPrice && "text-agg-muted-foreground!")
|
|
690
|
+
}
|
|
691
|
+
),
|
|
692
|
+
size: "small",
|
|
693
|
+
classNames: {
|
|
694
|
+
root: cn(
|
|
695
|
+
"agg-outcome-price",
|
|
696
|
+
"h-[30px] justify-center overflow-hidden px-0 text-agg-sm leading-agg-5",
|
|
697
|
+
"shrink-0 p-0! transition-all duration-300 ease-out",
|
|
698
|
+
isHighlightedBestPrice ? "agg-outcome-price-best ml-2 w-[68px] min-w-[68px] shadow-none" : cn(
|
|
699
|
+
"bg-agg-secondary-hover hover:bg-agg-tertiary",
|
|
700
|
+
hasVenueCompetition ? "agg-outcome-price-collapsed relative box-border w-[30px] min-w-[30px] group-hover/agg-event-card:w-[68px] group-hover/agg-event-card:min-w-[68px] group-hover/agg-event-card:gap-1" : "w-[68px] min-w-[68px]",
|
|
701
|
+
hasVenueCompetition && priceIndex > 0 && "-ml-3 group-hover/agg-event-card:ml-2"
|
|
702
|
+
),
|
|
703
|
+
isInteractive && "cursor-pointer",
|
|
704
|
+
classNames == null ? void 0 : classNames.badge
|
|
705
|
+
),
|
|
706
|
+
prefix: cn(
|
|
707
|
+
"flex shrink-0 items-center justify-center [&>svg]:size-3.5",
|
|
708
|
+
shouldCollapsePriceText && "pointer-events-none absolute inset-0 transition-[opacity] duration-300 ease-in group-hover/agg-event-card:pointer-events-auto group-hover/agg-event-card:static group-hover/agg-event-card:inset-auto"
|
|
709
|
+
),
|
|
710
|
+
text: cn(
|
|
711
|
+
"transition-[max-width,opacity] duration-300 ease-in",
|
|
712
|
+
price.isBest ? "text-agg-foreground" : "text-agg-muted-foreground",
|
|
713
|
+
shouldCollapsePriceText && "max-w-0 overflow-hidden! opacity-0 group-hover/agg-event-card:max-w-[40px] group-hover/agg-event-card:opacity-100"
|
|
714
|
+
)
|
|
715
|
+
},
|
|
716
|
+
onClick: isInteractive ? (eventToHandle) => {
|
|
717
|
+
handleOutcomeBadgeClick(eventToHandle, row.market, row.outcome, marketHref);
|
|
718
|
+
} : void 0,
|
|
719
|
+
onAuxClick: isInteractive ? (eventToHandle) => {
|
|
720
|
+
handleOutcomeBadgeClick(eventToHandle, row.market, row.outcome, marketHref);
|
|
721
|
+
} : void 0
|
|
722
|
+
},
|
|
723
|
+
`${price.market.id}:${price.outcome.id}`
|
|
724
|
+
);
|
|
725
|
+
};
|
|
726
|
+
return /* @__PURE__ */ jsxs(
|
|
727
|
+
Card,
|
|
728
|
+
{
|
|
729
|
+
className: cn(
|
|
730
|
+
"group/agg-event-card min-w-60 md:min-w-90",
|
|
731
|
+
baseCardClassName,
|
|
732
|
+
(onEventClick || href) && "cursor-pointer",
|
|
733
|
+
classNames == null ? void 0 : classNames.root
|
|
734
|
+
),
|
|
735
|
+
role: !href && onEventClick ? "button" : void 0,
|
|
736
|
+
tabIndex: !href && onEventClick ? 0 : void 0,
|
|
737
|
+
href,
|
|
738
|
+
onClick: handleClick,
|
|
739
|
+
onKeyDown: handleKeyDown,
|
|
740
|
+
"aria-label": ariaLabel != null ? ariaLabel : [resolvedTitle, resolvedTimestamp].filter(Boolean).join(" "),
|
|
741
|
+
withGradient: true,
|
|
742
|
+
children: [
|
|
743
|
+
/* @__PURE__ */ jsxs("div", { className: cn("agg-event-card-header flex items-center gap-4", classNames == null ? void 0 : classNames.header), children: [
|
|
744
|
+
/* @__PURE__ */ jsx(
|
|
745
|
+
RemoteImage,
|
|
746
|
+
{
|
|
747
|
+
src: optimizedImageUrl(resolvedImage, 40),
|
|
748
|
+
retinaSrc: retinaImageUrl(resolvedImage, 40),
|
|
749
|
+
alt: "",
|
|
750
|
+
classNames: {
|
|
751
|
+
root: "agg-event-image h-10 w-10 shrink-0 rounded-agg-lg object-cover",
|
|
752
|
+
image: "transition-transform duration-300 group-hover/agg-event-card:scale-110"
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
),
|
|
756
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 self-stretch", children: /* @__PURE__ */ jsxs("div", { className: "flex h-12 min-w-0 flex-col justify-center", children: [
|
|
757
|
+
/* @__PURE__ */ jsx(
|
|
758
|
+
Typography,
|
|
759
|
+
{
|
|
760
|
+
variant: "body-strong",
|
|
761
|
+
className: cn(
|
|
762
|
+
"agg-event-title",
|
|
763
|
+
"min-w-0 text-agg-base font-agg-bold leading-agg-6",
|
|
764
|
+
resolvedTimestamp ? "truncate whitespace-nowrap" : "text-wrap wrap-break-word line-clamp-2",
|
|
765
|
+
classNames == null ? void 0 : classNames.title
|
|
766
|
+
),
|
|
767
|
+
children: resolvedTitle
|
|
768
|
+
}
|
|
769
|
+
),
|
|
770
|
+
resolvedTimestamp ? /* @__PURE__ */ jsx("div", { className: "agg-event-timestamp-row mt-0.5 h-5 min-w-0", children: /* @__PURE__ */ jsx(
|
|
771
|
+
Typography,
|
|
772
|
+
{
|
|
773
|
+
variant: "body",
|
|
774
|
+
className: cn(
|
|
775
|
+
"agg-event-timestamp min-w-0 truncate",
|
|
776
|
+
"text-agg-sm leading-agg-5 text-agg-muted-foreground"
|
|
777
|
+
),
|
|
778
|
+
children: resolvedTimestamp
|
|
779
|
+
}
|
|
780
|
+
) }) : null
|
|
781
|
+
] }) })
|
|
782
|
+
] }),
|
|
783
|
+
/* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
|
|
784
|
+
/* @__PURE__ */ jsxs(
|
|
785
|
+
"div",
|
|
786
|
+
{
|
|
787
|
+
ref: outcomesContainerRef,
|
|
788
|
+
className: cn(
|
|
789
|
+
"agg-outcomes flex max-h-[76px] flex-col gap-4 overflow-y-auto rounded-agg-md [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
790
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-agg-primary focus-visible:ring-offset-2 focus-visible:ring-offset-agg-secondary",
|
|
791
|
+
classNames == null ? void 0 : classNames.outcomes
|
|
792
|
+
),
|
|
793
|
+
"aria-label": labels.marketDetails.marketOutcomesAria,
|
|
794
|
+
tabIndex: 0,
|
|
795
|
+
children: [
|
|
796
|
+
comparison.rows.map((row) => {
|
|
797
|
+
var _a2;
|
|
798
|
+
const arbitragePercent = (_a2 = arbitrageByOutcomeId == null ? void 0 : arbitrageByOutcomeId[row.outcome.id]) != null ? _a2 : arbitrageByOutcomeId == null ? void 0 : arbitrageByOutcomeId[row.market.id];
|
|
799
|
+
const arbReturn = arbReturnByVenueMarketId.get(row.market.id);
|
|
800
|
+
const priceGapPercent = arbReturn == null ? gapsByVenueMarketId.get(row.market.id) : arbReturn;
|
|
801
|
+
const priceGapSource = arbReturn == null ? "percent" : "fraction";
|
|
802
|
+
return /* @__PURE__ */ jsxs(
|
|
803
|
+
"div",
|
|
804
|
+
{
|
|
805
|
+
className: cn(
|
|
806
|
+
"agg-outcome-row",
|
|
807
|
+
"flex h-10 w-full flex-row items-center justify-between gap-3",
|
|
808
|
+
classNames == null ? void 0 : classNames.outcomeRow
|
|
809
|
+
),
|
|
810
|
+
children: [
|
|
811
|
+
/* @__PURE__ */ jsx("div", { className: "agg-outcome-label-row flex min-w-0 flex-1 flex-row items-center justify-start gap-2", children: /* @__PURE__ */ jsx(
|
|
812
|
+
Typography,
|
|
813
|
+
{
|
|
814
|
+
variant: "body",
|
|
815
|
+
className: "agg-outcome-label min-w-0 truncate text-agg-xs leading-agg-5 md:text-agg-base md:leading-agg-6",
|
|
816
|
+
children: row.label
|
|
817
|
+
}
|
|
818
|
+
) }),
|
|
819
|
+
/* @__PURE__ */ jsxs("div", { className: "agg-outcome-meta flex shrink-0 flex-row items-center justify-end gap-2", children: [
|
|
820
|
+
renderArbitrage(arbitragePercent),
|
|
821
|
+
renderPriceGapPill(priceGapPercent, priceGapSource),
|
|
822
|
+
/* @__PURE__ */ jsx("div", { className: "agg-outcome-price-strip relative flex shrink-0 items-center justify-end", children: isAwaitingMidpoints ? renderPriceStripSkeleton(row.prices.length) : row.prices.map(
|
|
823
|
+
(price, priceIndex) => renderComparisonPriceBadge(row, price, priceIndex)
|
|
824
|
+
) })
|
|
825
|
+
] })
|
|
826
|
+
]
|
|
827
|
+
},
|
|
828
|
+
row.id
|
|
829
|
+
);
|
|
830
|
+
}),
|
|
831
|
+
shouldRenderLoadingOutcomeRow ? /* @__PURE__ */ jsxs("div", { className: "agg-outcome-row-loading flex w-full items-center justify-between gap-3", children: [
|
|
832
|
+
/* @__PURE__ */ jsx(
|
|
833
|
+
"div",
|
|
834
|
+
{
|
|
835
|
+
"aria-hidden": "true",
|
|
836
|
+
className: "bg-agg-separator animate-pulse h-5 rounded-agg-sm w-[200px]"
|
|
837
|
+
}
|
|
838
|
+
),
|
|
839
|
+
/* @__PURE__ */ jsx(
|
|
840
|
+
"div",
|
|
841
|
+
{
|
|
842
|
+
"aria-hidden": "true",
|
|
843
|
+
className: "bg-agg-separator animate-pulse h-9 w-[100px] rounded-agg-full"
|
|
844
|
+
}
|
|
845
|
+
)
|
|
846
|
+
] }) : null
|
|
847
|
+
]
|
|
848
|
+
}
|
|
849
|
+
),
|
|
850
|
+
/* @__PURE__ */ jsx(
|
|
851
|
+
"div",
|
|
852
|
+
{
|
|
853
|
+
className: cn(
|
|
854
|
+
"agg-outcomes-scroll-gradient-top pointer-events-none absolute inset-x-0 top-0 z-10 bg-gradient-to-b from-agg-secondary to-transparent transition-opacity duration-150",
|
|
855
|
+
outcomesScrollState.hasOverflow && !outcomesScrollState.isAtTop ? "opacity-100" : "opacity-0"
|
|
856
|
+
),
|
|
857
|
+
style: { height: OUTCOMES_SCROLL_MASK_HEIGHT_PX }
|
|
858
|
+
}
|
|
859
|
+
),
|
|
860
|
+
/* @__PURE__ */ jsx(
|
|
861
|
+
"div",
|
|
862
|
+
{
|
|
863
|
+
className: cn(
|
|
864
|
+
"agg-outcomes-scroll-gradient-bottom pointer-events-none absolute inset-x-0 bottom-0 z-10 bg-gradient-to-t from-agg-secondary to-transparent transition-opacity duration-150",
|
|
865
|
+
outcomesScrollState.hasOverflow && !outcomesScrollState.isAtBottom ? "opacity-100" : "opacity-0"
|
|
866
|
+
),
|
|
867
|
+
style: { height: OUTCOMES_SCROLL_MASK_HEIGHT_PX }
|
|
868
|
+
}
|
|
869
|
+
)
|
|
870
|
+
] }),
|
|
871
|
+
/* @__PURE__ */ jsxs(
|
|
872
|
+
"div",
|
|
873
|
+
{
|
|
874
|
+
className: cn(
|
|
875
|
+
"agg-event-card-footer",
|
|
876
|
+
"flex items-center justify-between gap-5",
|
|
877
|
+
"text-agg-muted-foreground",
|
|
878
|
+
classNames == null ? void 0 : classNames.footer
|
|
879
|
+
),
|
|
880
|
+
children: [
|
|
881
|
+
/* @__PURE__ */ jsxs(
|
|
882
|
+
"div",
|
|
883
|
+
{
|
|
884
|
+
className: cn(
|
|
885
|
+
"agg-event-meta flex min-w-0 flex-1 items-center gap-2 text-agg-sm leading-agg-5 truncate"
|
|
886
|
+
),
|
|
887
|
+
children: [
|
|
888
|
+
outcomesScrollState.remainingMarkets > 0 ? /* @__PURE__ */ jsx(
|
|
889
|
+
Typography,
|
|
890
|
+
{
|
|
891
|
+
variant: "body",
|
|
892
|
+
className: "agg-event-remaining-markets shrink-0 text-agg-sm leading-agg-5 text-agg-muted-foreground",
|
|
893
|
+
children: labels.eventItem.remainingMarkets(outcomesScrollState.remainingMarkets)
|
|
894
|
+
}
|
|
895
|
+
) : null,
|
|
896
|
+
shouldShowMatchedVenueSummary ? /* @__PURE__ */ jsx("span", { className: "agg-event-matched-badge rounded-agg-full bg-agg-primary/10 px-2 py-[3px] text-agg-2xs font-agg-bold uppercase leading-agg-14 text-agg-primary", children: matchedCountLabel }) : null,
|
|
897
|
+
singleFooterVenue ? /* @__PURE__ */ jsxs("span", { className: "agg-event-single-venue flex min-w-0 items-center gap-1 overflow-hidden", children: [
|
|
898
|
+
/* @__PURE__ */ jsx(
|
|
899
|
+
VenueLogo,
|
|
900
|
+
{
|
|
901
|
+
venue: singleFooterVenue,
|
|
902
|
+
size: "small",
|
|
903
|
+
isMonochromatic: true,
|
|
904
|
+
className: "text-agg-muted-foreground! size-[14px]!"
|
|
905
|
+
}
|
|
906
|
+
),
|
|
907
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-agg-muted-foreground", children: resolveVenueLabel(singleFooterVenue, void 0, labels) })
|
|
908
|
+
] }) : null,
|
|
909
|
+
shouldShowMatchedVenueSummary && visibleFooterVenues.length > 0 ? /* @__PURE__ */ jsx("span", { className: "agg-event-venues flex items-center gap-1 overflow-hidden", children: visibleFooterVenues.map((venue) => (
|
|
910
|
+
// Muted at rest; hovering a logo crossfades it to the venue's colours.
|
|
911
|
+
/* @__PURE__ */ jsxs(
|
|
912
|
+
"span",
|
|
913
|
+
{
|
|
914
|
+
className: "agg-event-venue-logo group/agg-footer-venue relative inline-flex size-3.5 shrink-0",
|
|
915
|
+
title: resolveVenueLabel(venue, void 0, labels),
|
|
916
|
+
children: [
|
|
917
|
+
/* @__PURE__ */ jsx(
|
|
918
|
+
VenueLogo,
|
|
919
|
+
{
|
|
920
|
+
venue,
|
|
921
|
+
size: "small",
|
|
922
|
+
isMonochromatic: true,
|
|
923
|
+
className: cn(
|
|
924
|
+
"text-agg-muted-foreground! size-3.5!",
|
|
925
|
+
getMotionClassName(
|
|
926
|
+
config.features.enableAnimations,
|
|
927
|
+
"transition-opacity duration-150"
|
|
928
|
+
),
|
|
929
|
+
"group-hover/agg-footer-venue:opacity-0"
|
|
930
|
+
)
|
|
931
|
+
}
|
|
932
|
+
),
|
|
933
|
+
/* @__PURE__ */ jsx(
|
|
934
|
+
VenueLogo,
|
|
935
|
+
{
|
|
936
|
+
venue,
|
|
937
|
+
size: "small",
|
|
938
|
+
className: cn(
|
|
939
|
+
"absolute inset-0 size-3.5! opacity-0",
|
|
940
|
+
getMotionClassName(
|
|
941
|
+
config.features.enableAnimations,
|
|
942
|
+
"transition-opacity duration-150"
|
|
943
|
+
),
|
|
944
|
+
"group-hover/agg-footer-venue:opacity-100"
|
|
945
|
+
)
|
|
946
|
+
}
|
|
947
|
+
)
|
|
948
|
+
]
|
|
949
|
+
},
|
|
950
|
+
venue
|
|
951
|
+
)
|
|
952
|
+
)) }) : null
|
|
953
|
+
]
|
|
954
|
+
}
|
|
955
|
+
),
|
|
956
|
+
/* @__PURE__ */ jsx(
|
|
957
|
+
Typography,
|
|
958
|
+
{
|
|
959
|
+
variant: "label",
|
|
960
|
+
className: "agg-event-volume min-w-fit shrink-0 truncate whitespace-pre text-agg-sm text-agg-muted-foreground line-clamp-1",
|
|
961
|
+
children: volumeLabel
|
|
962
|
+
}
|
|
963
|
+
)
|
|
964
|
+
]
|
|
965
|
+
}
|
|
966
|
+
)
|
|
967
|
+
]
|
|
968
|
+
}
|
|
969
|
+
);
|
|
970
|
+
};
|
|
971
|
+
var EventListItemByEventId = (_a) => {
|
|
972
|
+
var _b = _a, {
|
|
973
|
+
eventId
|
|
974
|
+
} = _b, rest = __objRest(_b, [
|
|
975
|
+
"eventId"
|
|
976
|
+
]);
|
|
977
|
+
const {
|
|
978
|
+
event: fetchedEvent,
|
|
979
|
+
error,
|
|
980
|
+
isError,
|
|
981
|
+
isLoading
|
|
982
|
+
} = useVenueEvent({
|
|
983
|
+
eventId: eventId != null ? eventId : "",
|
|
984
|
+
enabled: !!eventId
|
|
985
|
+
});
|
|
986
|
+
const resolvedEvent = useMemo(() => {
|
|
987
|
+
return resolveEventListItemEvent(fetchedEvent);
|
|
988
|
+
}, [fetchedEvent]);
|
|
989
|
+
if (!eventId) {
|
|
990
|
+
return /* @__PURE__ */ jsx(EventListItemUnavailableState, { classNames: rest.classNames, ariaLabel: rest.ariaLabel });
|
|
991
|
+
}
|
|
992
|
+
if (isLoading) {
|
|
993
|
+
return /* @__PURE__ */ jsx(EventListItemLoadingState, { classNames: rest.classNames, ariaLabel: rest.ariaLabel });
|
|
994
|
+
}
|
|
995
|
+
if (isErrorWithStatus(error, 404)) {
|
|
996
|
+
return /* @__PURE__ */ jsx(EventListItemNotFoundState, { classNames: rest.classNames, ariaLabel: rest.ariaLabel });
|
|
997
|
+
}
|
|
998
|
+
if (!fetchedEvent && !isError) {
|
|
999
|
+
return /* @__PURE__ */ jsx(EventListItemLoadingState, { classNames: rest.classNames, ariaLabel: rest.ariaLabel });
|
|
1000
|
+
}
|
|
1001
|
+
if (!resolvedEvent) {
|
|
1002
|
+
return /* @__PURE__ */ jsx(EventListItemUnavailableState, { classNames: rest.classNames, ariaLabel: rest.ariaLabel });
|
|
1003
|
+
}
|
|
1004
|
+
return /* @__PURE__ */ jsx(EventListItemContent, __spreadValues({ event: resolvedEvent }, rest));
|
|
1005
|
+
};
|
|
1006
|
+
var EventListItem = (props) => {
|
|
1007
|
+
if (props.isLoading) {
|
|
1008
|
+
return /* @__PURE__ */ jsx(EventListItemLoadingState, { classNames: props.classNames, ariaLabel: props.ariaLabel });
|
|
1009
|
+
}
|
|
1010
|
+
if ("event" in props && props.event) {
|
|
1011
|
+
const _a = props, { event } = _a, rest = __objRest(_a, ["event"]);
|
|
1012
|
+
return /* @__PURE__ */ jsx(EventListItemContent, __spreadValues({ event }, rest));
|
|
1013
|
+
}
|
|
1014
|
+
return /* @__PURE__ */ jsx(EventListItemByEventId, __spreadValues({}, props));
|
|
1015
|
+
};
|
|
1016
|
+
EventListItem.displayName = "EventListItem";
|
|
1017
|
+
var EventListItemV2 = (props) => {
|
|
1018
|
+
return /* @__PURE__ */ jsx(EventListItem, __spreadValues({}, props));
|
|
1019
|
+
};
|
|
1020
|
+
EventListItemV2.displayName = "EventListItemV2";
|
|
1021
|
+
|
|
1022
|
+
// src/events/list/index.tsx
|
|
1023
|
+
import {
|
|
1024
|
+
MarketStatus,
|
|
1025
|
+
getVisibleVenueIdsByConfig,
|
|
1026
|
+
useAppConfig as useAppConfig2,
|
|
1027
|
+
useCategories,
|
|
1028
|
+
useCategoryChildren,
|
|
1029
|
+
useLabels as useLabels3,
|
|
1030
|
+
useSdkUiConfig as useSdkUiConfig2,
|
|
1031
|
+
useVenueEvents,
|
|
1032
|
+
useVenueMarketMidpoints as useVenueMarketMidpoints2
|
|
1033
|
+
} from "@agg-build/hooks";
|
|
1034
|
+
import { VENUES } from "@agg-build/sdk";
|
|
1035
|
+
import * as Dialog from "@radix-ui/react-dialog";
|
|
1036
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo4, useRef as useRef3, useState as useState3 } from "react";
|
|
1037
|
+
|
|
1038
|
+
// src/events/list/category-sidebar.tsx
|
|
1039
|
+
import { useMemo as useMemo2 } from "react";
|
|
1040
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1041
|
+
var rowBase = cn(
|
|
1042
|
+
"flex min-h-11 w-full items-center gap-3 rounded-[6px] px-3 py-3",
|
|
1043
|
+
"text-left text-agg-sm font-agg-normal leading-agg-5",
|
|
1044
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-agg-primary focus-visible:ring-offset-1 focus-visible:ring-offset-agg-secondary"
|
|
1045
|
+
);
|
|
1046
|
+
var idleRowClassName = cn(
|
|
1047
|
+
rowBase,
|
|
1048
|
+
"cursor-pointer text-agg-foreground hover:bg-agg-secondary-hover"
|
|
1049
|
+
);
|
|
1050
|
+
var selectedRowClassName = cn(rowBase, "cursor-pointer bg-agg-primary/10 text-agg-primary");
|
|
1051
|
+
var CategorySidebar = ({
|
|
1052
|
+
baseCategoryId,
|
|
1053
|
+
childrenByParentId,
|
|
1054
|
+
categoryPath,
|
|
1055
|
+
collapsedCategoryIds,
|
|
1056
|
+
totalEventCount,
|
|
1057
|
+
labels,
|
|
1058
|
+
onSelectAll,
|
|
1059
|
+
onToggleCategory
|
|
1060
|
+
}) => {
|
|
1061
|
+
const isDrilledIn = categoryPath.length > 0;
|
|
1062
|
+
const sortedBaseChildren = useMemo2(() => {
|
|
1063
|
+
var _a;
|
|
1064
|
+
if (!baseCategoryId) return [];
|
|
1065
|
+
const children = [...(_a = childrenByParentId.get(baseCategoryId)) != null ? _a : []];
|
|
1066
|
+
return children.sort((a, b) => {
|
|
1067
|
+
var _a2, _b, _c, _d;
|
|
1068
|
+
const aHasChildren = ((_b = (_a2 = childrenByParentId.get(a.id)) == null ? void 0 : _a2.length) != null ? _b : 0) > 0;
|
|
1069
|
+
const bHasChildren = ((_d = (_c = childrenByParentId.get(b.id)) == null ? void 0 : _c.length) != null ? _d : 0) > 0;
|
|
1070
|
+
if (aHasChildren === bHasChildren) return 0;
|
|
1071
|
+
return aHasChildren ? -1 : 1;
|
|
1072
|
+
});
|
|
1073
|
+
}, [baseCategoryId, childrenByParentId]);
|
|
1074
|
+
const renderRow = ({
|
|
1075
|
+
entry,
|
|
1076
|
+
isExpanded,
|
|
1077
|
+
isSelected,
|
|
1078
|
+
onClick
|
|
1079
|
+
}) => {
|
|
1080
|
+
var _a, _b;
|
|
1081
|
+
const hasKnownChildren = ((_b = (_a = childrenByParentId.get(entry.id)) == null ? void 0 : _a.length) != null ? _b : 0) > 0;
|
|
1082
|
+
return /* @__PURE__ */ jsxs2(
|
|
1083
|
+
"button",
|
|
1084
|
+
{
|
|
1085
|
+
type: "button",
|
|
1086
|
+
"aria-current": isSelected ? "true" : void 0,
|
|
1087
|
+
"aria-expanded": hasKnownChildren ? isExpanded : void 0,
|
|
1088
|
+
className: isSelected ? selectedRowClassName : idleRowClassName,
|
|
1089
|
+
onClick,
|
|
1090
|
+
children: [
|
|
1091
|
+
/* @__PURE__ */ jsx2("span", { className: "min-w-0 flex-1 truncate first-letter:uppercase", children: entry.label }),
|
|
1092
|
+
hasKnownChildren ? /* @__PURE__ */ jsx2(
|
|
1093
|
+
Icon,
|
|
1094
|
+
{
|
|
1095
|
+
name: isExpanded ? "chevron-up" : "chevron-down",
|
|
1096
|
+
size: "small",
|
|
1097
|
+
color: "currentColor",
|
|
1098
|
+
className: "shrink-0 text-agg-muted-foreground"
|
|
1099
|
+
}
|
|
1100
|
+
) : /* @__PURE__ */ jsx2("span", { className: "shrink-0 text-agg-muted-foreground", children: entry.eventCount })
|
|
1101
|
+
]
|
|
1102
|
+
},
|
|
1103
|
+
entry.id
|
|
1104
|
+
);
|
|
1105
|
+
};
|
|
1106
|
+
const renderBranch = (category, depth) => {
|
|
1107
|
+
var _a, _b, _c, _d, _e;
|
|
1108
|
+
const label = (_a = category.displayName) != null ? _a : category.name;
|
|
1109
|
+
const entry = {
|
|
1110
|
+
id: category.id,
|
|
1111
|
+
label,
|
|
1112
|
+
eventCount: (_b = category.eventCount) != null ? _b : 0
|
|
1113
|
+
};
|
|
1114
|
+
const childCategories = (_c = childrenByParentId.get(category.id)) != null ? _c : [];
|
|
1115
|
+
const hasKnownChildren = childCategories.length > 0;
|
|
1116
|
+
const isExpanded = ((_d = categoryPath[depth]) == null ? void 0 : _d.id) === category.id && !collapsedCategoryIds.has(category.id);
|
|
1117
|
+
const isSelected = ((_e = categoryPath[depth]) == null ? void 0 : _e.id) === category.id && categoryPath.length === depth + 1;
|
|
1118
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex w-full flex-col", children: [
|
|
1119
|
+
renderRow({
|
|
1120
|
+
entry,
|
|
1121
|
+
isExpanded,
|
|
1122
|
+
isSelected,
|
|
1123
|
+
onClick: () => onToggleCategory({ entry, depth, hasKnownChildren, isExpanded, isSelected })
|
|
1124
|
+
}),
|
|
1125
|
+
/* @__PURE__ */ jsx2(
|
|
1126
|
+
"div",
|
|
1127
|
+
{
|
|
1128
|
+
className: cn(
|
|
1129
|
+
"grid transition-[grid-template-rows] duration-150 ease-in-out motion-reduce:transition-none",
|
|
1130
|
+
isExpanded ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
|
|
1131
|
+
),
|
|
1132
|
+
children: /* @__PURE__ */ jsx2("div", { className: "overflow-hidden", children: /* @__PURE__ */ jsx2("div", { className: "flex w-full flex-col gap-1 pl-4 pt-1", children: childCategories.map((child) => renderBranch(child, depth + 1)) }) })
|
|
1133
|
+
}
|
|
1134
|
+
)
|
|
1135
|
+
] }, category.id);
|
|
1136
|
+
};
|
|
1137
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex w-full flex-col gap-1", children: [
|
|
1138
|
+
/* @__PURE__ */ jsxs2(
|
|
1139
|
+
"button",
|
|
1140
|
+
{
|
|
1141
|
+
type: "button",
|
|
1142
|
+
"aria-current": !isDrilledIn ? "true" : void 0,
|
|
1143
|
+
className: !isDrilledIn ? selectedRowClassName : idleRowClassName,
|
|
1144
|
+
onClick: onSelectAll,
|
|
1145
|
+
children: [
|
|
1146
|
+
/* @__PURE__ */ jsx2("span", { className: "min-w-0 flex-1 truncate", children: labels.subcategoriesAll }),
|
|
1147
|
+
/* @__PURE__ */ jsx2("span", { className: "shrink-0 text-agg-muted-foreground", children: totalEventCount })
|
|
1148
|
+
]
|
|
1149
|
+
}
|
|
1150
|
+
),
|
|
1151
|
+
sortedBaseChildren.map((category) => renderBranch(category, 0))
|
|
1152
|
+
] });
|
|
1153
|
+
};
|
|
1154
|
+
CategorySidebar.displayName = "CategorySidebar";
|
|
1155
|
+
|
|
1156
|
+
// src/events/list/event-list-tabs.tsx
|
|
1157
|
+
import { getVenueAvailabilityState, useAppConfig, useGeoBlock, useLabels as useLabels2 } from "@agg-build/hooks";
|
|
1158
|
+
import { getEffectiveDisabledVenues, isVenueInactive } from "@agg-build/sdk";
|
|
1159
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo3, useRef as useRef2, useState as useState2 } from "react";
|
|
1160
|
+
|
|
1161
|
+
// src/events/list/event-list.constants.ts
|
|
1162
|
+
import { sortVenues as sortVenues2 } from "@agg-build/hooks";
|
|
1163
|
+
import { MatchStatus, Venue } from "@agg-build/sdk";
|
|
1164
|
+
var DEFAULT_EVENTS_LIMIT = 50;
|
|
1165
|
+
var DEFAULT_EVENT_LIST_SORT = "volume24hr";
|
|
1166
|
+
var PLACEHOLDER_SKELETON_MIN_ITEMS = 6;
|
|
1167
|
+
var EVENT_LIST_SORT_VALUES = [
|
|
1168
|
+
"volume24hr",
|
|
1169
|
+
"topArbitrage",
|
|
1170
|
+
"volume",
|
|
1171
|
+
"endDate"
|
|
1172
|
+
];
|
|
1173
|
+
var getDefaultEventListTabs = (labels) => {
|
|
1174
|
+
const tabs = [
|
|
1175
|
+
{
|
|
1176
|
+
value: "matched",
|
|
1177
|
+
label: labels.eventList.matchedTab,
|
|
1178
|
+
iconName: "circle-overlap",
|
|
1179
|
+
matchStatus: [MatchStatus.matched, MatchStatus.verified]
|
|
1180
|
+
},
|
|
1181
|
+
{
|
|
1182
|
+
value: "all",
|
|
1183
|
+
label: labels.eventList.allTab,
|
|
1184
|
+
iconName: "apps"
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
value: Venue.polymarket,
|
|
1188
|
+
label: labels.venues.polymarket,
|
|
1189
|
+
venueLogo: Venue.polymarket,
|
|
1190
|
+
venues: [Venue.polymarket]
|
|
1191
|
+
},
|
|
1192
|
+
{
|
|
1193
|
+
value: Venue.kalshi,
|
|
1194
|
+
label: labels.venues.kalshi,
|
|
1195
|
+
venueLogo: Venue.kalshi,
|
|
1196
|
+
venues: [Venue.kalshi]
|
|
1197
|
+
},
|
|
1198
|
+
{
|
|
1199
|
+
value: Venue.limitless,
|
|
1200
|
+
label: labels.venues.limitless,
|
|
1201
|
+
venueLogo: Venue.limitless,
|
|
1202
|
+
venues: [Venue.limitless]
|
|
1203
|
+
},
|
|
1204
|
+
{
|
|
1205
|
+
value: Venue.predict,
|
|
1206
|
+
label: labels.venues.predict,
|
|
1207
|
+
venueLogo: Venue.predict,
|
|
1208
|
+
venues: [Venue.predict]
|
|
1209
|
+
},
|
|
1210
|
+
{
|
|
1211
|
+
value: Venue.pred,
|
|
1212
|
+
label: labels.venues.pred,
|
|
1213
|
+
venueLogo: Venue.pred,
|
|
1214
|
+
venues: [Venue.pred]
|
|
1215
|
+
},
|
|
1216
|
+
{
|
|
1217
|
+
value: Venue.hyperliquid,
|
|
1218
|
+
label: labels.venues.hyperliquid,
|
|
1219
|
+
venueLogo: Venue.hyperliquid,
|
|
1220
|
+
venues: [Venue.hyperliquid]
|
|
1221
|
+
// isComingSoon: true,
|
|
1222
|
+
},
|
|
1223
|
+
{
|
|
1224
|
+
value: Venue.myriad,
|
|
1225
|
+
label: labels.venues.myriad,
|
|
1226
|
+
venueLogo: Venue.myriad,
|
|
1227
|
+
venues: [Venue.myriad]
|
|
1228
|
+
// isComingSoon: true,
|
|
1229
|
+
},
|
|
1230
|
+
{
|
|
1231
|
+
value: Venue.novig,
|
|
1232
|
+
label: labels.venues.novig,
|
|
1233
|
+
venueLogo: Venue.novig,
|
|
1234
|
+
venues: [Venue.novig]
|
|
1235
|
+
},
|
|
1236
|
+
{
|
|
1237
|
+
value: Venue.prophetx,
|
|
1238
|
+
label: labels.venues.prophetx,
|
|
1239
|
+
venueLogo: Venue.prophetx,
|
|
1240
|
+
venues: [Venue.prophetx]
|
|
1241
|
+
},
|
|
1242
|
+
{
|
|
1243
|
+
value: Venue.opinion,
|
|
1244
|
+
label: labels.venues.opinion,
|
|
1245
|
+
venueLogo: Venue.opinion,
|
|
1246
|
+
venues: [Venue.opinion],
|
|
1247
|
+
isComingSoon: true
|
|
1248
|
+
}
|
|
1249
|
+
];
|
|
1250
|
+
const venueRank = new Map(
|
|
1251
|
+
sortVenues2(tabs.flatMap((tab) => tab.venueLogo ? [tab.venueLogo] : [])).map((venue, i) => [
|
|
1252
|
+
venue,
|
|
1253
|
+
i
|
|
1254
|
+
])
|
|
1255
|
+
);
|
|
1256
|
+
const rank = (tab) => {
|
|
1257
|
+
var _a;
|
|
1258
|
+
return tab.venueLogo ? 1 + ((_a = venueRank.get(tab.venueLogo)) != null ? _a : venueRank.size) : 0;
|
|
1259
|
+
};
|
|
1260
|
+
return [...tabs].sort((a, b) => rank(a) - rank(b));
|
|
1261
|
+
};
|
|
1262
|
+
|
|
1263
|
+
// src/events/list/event-list-tabs.tsx
|
|
1264
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1265
|
+
var DEFAULT_HIDDEN_VENUES = new Set(getEffectiveDisabledVenues(void 0));
|
|
1266
|
+
var renderTabIcon = (tab, isActive) => {
|
|
1267
|
+
if (tab.iconName === "warning-filled") {
|
|
1268
|
+
return /* @__PURE__ */ jsx3(Icon, { name: "warning-filled", size: "small", color: "currentColor" });
|
|
1269
|
+
}
|
|
1270
|
+
if (tab.venueLogo) {
|
|
1271
|
+
return /* @__PURE__ */ jsx3(VenueLogo, { venue: tab.venueLogo, size: "small" });
|
|
1272
|
+
}
|
|
1273
|
+
if (!tab.iconName) return null;
|
|
1274
|
+
return /* @__PURE__ */ jsx3(
|
|
1275
|
+
Icon,
|
|
1276
|
+
{
|
|
1277
|
+
name: tab.iconName,
|
|
1278
|
+
size: "small",
|
|
1279
|
+
color: isActive ? "var(--agg-color-primary)" : "var(--agg-color-foreground)"
|
|
1280
|
+
}
|
|
1281
|
+
);
|
|
1282
|
+
};
|
|
1283
|
+
var useEventListTabs = (tabs) => {
|
|
1284
|
+
const labels = useLabels2();
|
|
1285
|
+
const { disabledVenues, isLoading: isAppConfigLoading } = useAppConfig();
|
|
1286
|
+
const { isLocationBlocked } = useGeoBlock();
|
|
1287
|
+
return useMemo3(() => {
|
|
1288
|
+
const baseTabs = tabs != null ? tabs : getDefaultEventListTabs(labels);
|
|
1289
|
+
return baseTabs.flatMap((tab) => {
|
|
1290
|
+
if (!tab.venueLogo) return [tab];
|
|
1291
|
+
const availabilityState = getVenueAvailabilityState({
|
|
1292
|
+
venueId: tab.venueLogo,
|
|
1293
|
+
disabledVenues,
|
|
1294
|
+
// A globally inactive or default-disabled venue is hidden until
|
|
1295
|
+
// `/app/config` resolves. That prevents partner-opt-in venues such as
|
|
1296
|
+
// Novig from flashing briefly for apps that still disable them, while
|
|
1297
|
+
// ordinary active venues continue rendering immediately.
|
|
1298
|
+
isConfigLoading: isAppConfigLoading && (isVenueInactive(tab.venueLogo) || DEFAULT_HIDDEN_VENUES.has(tab.venueLogo)),
|
|
1299
|
+
isLocationBlocked
|
|
1300
|
+
});
|
|
1301
|
+
if (availabilityState === "hidden") return [];
|
|
1302
|
+
return [
|
|
1303
|
+
__spreadProps(__spreadValues({}, tab), {
|
|
1304
|
+
disabled: tab.disabled || availabilityState === "geoblocked",
|
|
1305
|
+
label: availabilityState === "geoblocked" ? `${tab.label} (${labels.trading.venueUnavailableInRegion})` : tab.label,
|
|
1306
|
+
iconName: availabilityState === "geoblocked" ? "warning-filled" : tab.iconName
|
|
1307
|
+
})
|
|
1308
|
+
];
|
|
1309
|
+
});
|
|
1310
|
+
}, [tabs, labels, disabledVenues, isAppConfigLoading, isLocationBlocked]);
|
|
1311
|
+
};
|
|
1312
|
+
var EventListTabs = ({
|
|
1313
|
+
tabs,
|
|
1314
|
+
activeTab,
|
|
1315
|
+
onTabChange,
|
|
1316
|
+
ariaLabel,
|
|
1317
|
+
className,
|
|
1318
|
+
overflowBehavior
|
|
1319
|
+
}) => {
|
|
1320
|
+
const resolvedTabs = useEventListTabs(tabs);
|
|
1321
|
+
useEffect2(() => {
|
|
1322
|
+
const fallbackTab = resolvedTabs.find((tab) => !tab.disabled);
|
|
1323
|
+
if (!fallbackTab) return;
|
|
1324
|
+
if (resolvedTabs.some((tab) => tab.value === activeTab && !tab.disabled)) return;
|
|
1325
|
+
onTabChange(fallbackTab.value);
|
|
1326
|
+
}, [activeTab, onTabChange, resolvedTabs]);
|
|
1327
|
+
const items = useMemo3(() => {
|
|
1328
|
+
return resolvedTabs.map((tab) => {
|
|
1329
|
+
const isActive = tab.value === activeTab;
|
|
1330
|
+
return {
|
|
1331
|
+
value: tab.value,
|
|
1332
|
+
label: tab.label,
|
|
1333
|
+
icon: renderTabIcon(tab, isActive),
|
|
1334
|
+
disabled: tab.disabled,
|
|
1335
|
+
isComingSoon: tab.isComingSoon
|
|
1336
|
+
};
|
|
1337
|
+
});
|
|
1338
|
+
}, [activeTab, resolvedTabs]);
|
|
1339
|
+
return /* @__PURE__ */ jsx3(
|
|
1340
|
+
Tabs,
|
|
1341
|
+
{
|
|
1342
|
+
ariaLabel,
|
|
1343
|
+
className,
|
|
1344
|
+
items,
|
|
1345
|
+
overflowBehavior,
|
|
1346
|
+
value: activeTab,
|
|
1347
|
+
onChange: onTabChange
|
|
1348
|
+
}
|
|
1349
|
+
);
|
|
1350
|
+
};
|
|
1351
|
+
EventListTabs.displayName = "EventListTabs";
|
|
1352
|
+
var useEventListTabsHeaderOverflow = (recomputeOn, options) => {
|
|
1353
|
+
const headerRef = useRef2(null);
|
|
1354
|
+
const titleRef = useRef2(null);
|
|
1355
|
+
const requiredTabsWidthRef = useRef2(0);
|
|
1356
|
+
const [shouldUseSelectOverflow, setShouldUseSelectOverflow] = useState2(false);
|
|
1357
|
+
const updateTabsOverflowBehavior = useCallback2(() => {
|
|
1358
|
+
var _a;
|
|
1359
|
+
if (typeof window === "undefined") return;
|
|
1360
|
+
const headerElement = headerRef.current;
|
|
1361
|
+
const titleElement = titleRef.current;
|
|
1362
|
+
if (!headerElement || !titleElement) return;
|
|
1363
|
+
const headerStyles = window.getComputedStyle(headerElement);
|
|
1364
|
+
const rawGap = headerStyles.columnGap || headerStyles.gap || "0";
|
|
1365
|
+
const horizontalGap = Number.parseFloat(rawGap) || 0;
|
|
1366
|
+
const availableTabsWidth = headerElement.clientWidth - titleElement.getBoundingClientRect().width - horizontalGap;
|
|
1367
|
+
if (availableTabsWidth <= 0) {
|
|
1368
|
+
setShouldUseSelectOverflow(true);
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
const minTabsInlineWidthForSelect = options == null ? void 0 : options.minTabsInlineWidthForSelect;
|
|
1372
|
+
if (typeof minTabsInlineWidthForSelect === "number" && availableTabsWidth < minTabsInlineWidthForSelect) {
|
|
1373
|
+
setShouldUseSelectOverflow(true);
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
const preferSelectOnOverflow = (_a = options == null ? void 0 : options.preferSelectOnOverflow) != null ? _a : true;
|
|
1377
|
+
if (!preferSelectOnOverflow) {
|
|
1378
|
+
setShouldUseSelectOverflow(false);
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
const tabListElement = headerElement.querySelector(".agg-tab-list");
|
|
1382
|
+
if (tabListElement) {
|
|
1383
|
+
const currentRequiredWidth = tabListElement.scrollWidth;
|
|
1384
|
+
if (currentRequiredWidth > 0) {
|
|
1385
|
+
requiredTabsWidthRef.current = currentRequiredWidth;
|
|
1386
|
+
}
|
|
1387
|
+
const hasRealOverflow = tabListElement.scrollWidth - tabListElement.clientWidth > 1;
|
|
1388
|
+
setShouldUseSelectOverflow(hasRealOverflow);
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
if (requiredTabsWidthRef.current <= 0) return;
|
|
1392
|
+
setShouldUseSelectOverflow(requiredTabsWidthRef.current > availableTabsWidth);
|
|
1393
|
+
}, [options == null ? void 0 : options.minTabsInlineWidthForSelect, options == null ? void 0 : options.preferSelectOnOverflow]);
|
|
1394
|
+
useEffect2(() => {
|
|
1395
|
+
updateTabsOverflowBehavior();
|
|
1396
|
+
}, [recomputeOn, updateTabsOverflowBehavior]);
|
|
1397
|
+
useEffect2(() => {
|
|
1398
|
+
if (typeof window === "undefined") return;
|
|
1399
|
+
const handleResize = () => {
|
|
1400
|
+
updateTabsOverflowBehavior();
|
|
1401
|
+
};
|
|
1402
|
+
window.addEventListener("resize", handleResize);
|
|
1403
|
+
return () => {
|
|
1404
|
+
window.removeEventListener("resize", handleResize);
|
|
1405
|
+
};
|
|
1406
|
+
}, [updateTabsOverflowBehavior]);
|
|
1407
|
+
useEffect2(() => {
|
|
1408
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
1409
|
+
const headerElement = headerRef.current;
|
|
1410
|
+
const titleElement = titleRef.current;
|
|
1411
|
+
if (!headerElement || !titleElement) return;
|
|
1412
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
1413
|
+
updateTabsOverflowBehavior();
|
|
1414
|
+
});
|
|
1415
|
+
resizeObserver.observe(headerElement);
|
|
1416
|
+
resizeObserver.observe(titleElement);
|
|
1417
|
+
return () => {
|
|
1418
|
+
resizeObserver.disconnect();
|
|
1419
|
+
};
|
|
1420
|
+
}, [updateTabsOverflowBehavior]);
|
|
1421
|
+
return { headerRef, titleRef, shouldUseSelectOverflow };
|
|
1422
|
+
};
|
|
1423
|
+
|
|
1424
|
+
// src/events/list/index.tsx
|
|
1425
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1426
|
+
var SORT_ICON_BY_VALUE = {
|
|
1427
|
+
volume24hr: "sort-volume-24hr",
|
|
1428
|
+
topArbitrage: "sort-top-arbitrage",
|
|
1429
|
+
volume: "sort-volume",
|
|
1430
|
+
endDate: "sort-end-date"
|
|
1431
|
+
};
|
|
1432
|
+
var resolveSortQueryParams = (value) => {
|
|
1433
|
+
if (value === "volume") {
|
|
1434
|
+
return { sortBy: "volume", sortDir: "desc" };
|
|
1435
|
+
}
|
|
1436
|
+
if (value === "endDate") {
|
|
1437
|
+
return { sortBy: "endDate", sortDir: "asc" };
|
|
1438
|
+
}
|
|
1439
|
+
if (value === "topArbitrage") {
|
|
1440
|
+
return {
|
|
1441
|
+
sortBy: "arbReturn",
|
|
1442
|
+
sortDir: "desc"
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
return { sortBy: "volume24hr", sortDir: "desc" };
|
|
1446
|
+
};
|
|
1447
|
+
var collectEventListVenueMarkets = (events) => {
|
|
1448
|
+
return events.flatMap((event) => {
|
|
1449
|
+
var _a;
|
|
1450
|
+
return (_a = event.venueMarkets) != null ? _a : [];
|
|
1451
|
+
});
|
|
1452
|
+
};
|
|
1453
|
+
var collectMidpointVenueMarketIds = (venueMarkets) => {
|
|
1454
|
+
var _a;
|
|
1455
|
+
const ids = [];
|
|
1456
|
+
for (const market of venueMarkets) {
|
|
1457
|
+
ids.push(market.id);
|
|
1458
|
+
for (const sibling of (_a = market.matchedVenueMarkets) != null ? _a : []) {
|
|
1459
|
+
ids.push(sibling.id);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
return [...new Set(ids)];
|
|
1463
|
+
};
|
|
1464
|
+
var EventList = ({
|
|
1465
|
+
title,
|
|
1466
|
+
limit = DEFAULT_EVENTS_LIMIT,
|
|
1467
|
+
maxVisibleItems,
|
|
1468
|
+
search,
|
|
1469
|
+
categoryIds,
|
|
1470
|
+
onCategoryRootChange,
|
|
1471
|
+
onEventClick,
|
|
1472
|
+
onMarketClick,
|
|
1473
|
+
getMarketHref,
|
|
1474
|
+
getEventHref,
|
|
1475
|
+
initialVenueTab,
|
|
1476
|
+
activeVenueTab: controlledActiveVenueTab,
|
|
1477
|
+
onActiveVenueTabChange,
|
|
1478
|
+
selectedSort: controlledSelectedSort,
|
|
1479
|
+
onSelectedSortChange,
|
|
1480
|
+
categoryPath: controlledCategoryPath,
|
|
1481
|
+
onCategoryPathChange,
|
|
1482
|
+
initialLoadedPageCount,
|
|
1483
|
+
stateRef
|
|
1484
|
+
}) => {
|
|
1485
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1486
|
+
const labels = useLabels3();
|
|
1487
|
+
const { disabledVenues } = useAppConfig2();
|
|
1488
|
+
const {
|
|
1489
|
+
features: { enableVenueEventDiscoveryFilters, showSportsMarkets }
|
|
1490
|
+
} = useSdkUiConfig2();
|
|
1491
|
+
const isDiscoveryFiltersEnabled = enableVenueEventDiscoveryFilters && !search;
|
|
1492
|
+
const resolvedTabs = useEventListTabs();
|
|
1493
|
+
const visibleVenues = useMemo4(
|
|
1494
|
+
() => disabledVenues.length === 0 ? void 0 : getVisibleVenueIdsByConfig(VENUES, disabledVenues),
|
|
1495
|
+
[disabledVenues]
|
|
1496
|
+
);
|
|
1497
|
+
const [internalActiveTabValue, setInternalActiveTabValue] = useState3(
|
|
1498
|
+
(_b = initialVenueTab != null ? initialVenueTab : (_a = resolvedTabs[0]) == null ? void 0 : _a.value) != null ? _b : "matched"
|
|
1499
|
+
);
|
|
1500
|
+
const activeTabValue = controlledActiveVenueTab != null ? controlledActiveVenueTab : internalActiveTabValue;
|
|
1501
|
+
const [internalSelectedSort, setInternalSelectedSort] = useState3(DEFAULT_EVENT_LIST_SORT);
|
|
1502
|
+
const selectedSort = controlledSelectedSort != null ? controlledSelectedSort : internalSelectedSort;
|
|
1503
|
+
const [isSubcategoriesModalOpen, setIsSubcategoriesModalOpen] = useState3(false);
|
|
1504
|
+
const [internalCategoryPath, setInternalCategoryPath] = useState3([]);
|
|
1505
|
+
const categoryPath = controlledCategoryPath != null ? controlledCategoryPath : internalCategoryPath;
|
|
1506
|
+
const [collapsedCategoryIds, setCollapsedCategoryIds] = useState3(() => /* @__PURE__ */ new Set());
|
|
1507
|
+
const handleActiveTabChange = useCallback3(
|
|
1508
|
+
(value) => {
|
|
1509
|
+
if (controlledActiveVenueTab == null) setInternalActiveTabValue(value);
|
|
1510
|
+
onActiveVenueTabChange == null ? void 0 : onActiveVenueTabChange(value, { history: "push" });
|
|
1511
|
+
},
|
|
1512
|
+
[controlledActiveVenueTab, onActiveVenueTabChange]
|
|
1513
|
+
);
|
|
1514
|
+
const handleSelectedSortChange = useCallback3(
|
|
1515
|
+
(value) => {
|
|
1516
|
+
if (controlledSelectedSort == null) setInternalSelectedSort(value);
|
|
1517
|
+
onSelectedSortChange == null ? void 0 : onSelectedSortChange(value, { history: "push" });
|
|
1518
|
+
},
|
|
1519
|
+
[controlledSelectedSort, onSelectedSortChange]
|
|
1520
|
+
);
|
|
1521
|
+
const handleCategoryPathChange = useCallback3(
|
|
1522
|
+
(value, options) => {
|
|
1523
|
+
if (controlledCategoryPath == null) setInternalCategoryPath(value);
|
|
1524
|
+
onCategoryPathChange == null ? void 0 : onCategoryPathChange(value, options);
|
|
1525
|
+
},
|
|
1526
|
+
[controlledCategoryPath, onCategoryPathChange]
|
|
1527
|
+
);
|
|
1528
|
+
const sortItems = useMemo4(() => {
|
|
1529
|
+
return [
|
|
1530
|
+
{
|
|
1531
|
+
value: "volume24hr",
|
|
1532
|
+
label: labels.eventList.sortBy24hVolume,
|
|
1533
|
+
icon: /* @__PURE__ */ jsx4(Icon, { name: SORT_ICON_BY_VALUE.volume24hr, size: "small", color: "currentColor" })
|
|
1534
|
+
},
|
|
1535
|
+
{
|
|
1536
|
+
value: "topArbitrage",
|
|
1537
|
+
label: labels.eventList.sortByTopArbitrage,
|
|
1538
|
+
icon: /* @__PURE__ */ jsx4(Icon, { name: SORT_ICON_BY_VALUE.topArbitrage, size: "small", color: "currentColor" })
|
|
1539
|
+
},
|
|
1540
|
+
{
|
|
1541
|
+
value: "volume",
|
|
1542
|
+
label: labels.eventList.sortByTotalVolume,
|
|
1543
|
+
icon: /* @__PURE__ */ jsx4(Icon, { name: SORT_ICON_BY_VALUE.volume, size: "small", color: "currentColor" })
|
|
1544
|
+
},
|
|
1545
|
+
{
|
|
1546
|
+
value: "endDate",
|
|
1547
|
+
label: labels.eventList.sortByEndingSoon,
|
|
1548
|
+
icon: /* @__PURE__ */ jsx4(Icon, { name: SORT_ICON_BY_VALUE.endDate, size: "small", color: "currentColor" })
|
|
1549
|
+
}
|
|
1550
|
+
];
|
|
1551
|
+
}, [
|
|
1552
|
+
labels.eventList.sortBy24hVolume,
|
|
1553
|
+
labels.eventList.sortByEndingSoon,
|
|
1554
|
+
labels.eventList.sortByTopArbitrage,
|
|
1555
|
+
labels.eventList.sortByTotalVolume
|
|
1556
|
+
]);
|
|
1557
|
+
const baseCategoryId = (_c = categoryIds == null ? void 0 : categoryIds[0]) != null ? _c : null;
|
|
1558
|
+
const previousBaseCategoryIdRef = useRef3(baseCategoryId);
|
|
1559
|
+
useEffect3(() => {
|
|
1560
|
+
var _a2, _b2;
|
|
1561
|
+
if (previousBaseCategoryIdRef.current === baseCategoryId) return;
|
|
1562
|
+
previousBaseCategoryIdRef.current = baseCategoryId;
|
|
1563
|
+
if (controlledActiveVenueTab == null) {
|
|
1564
|
+
setInternalActiveTabValue((_b2 = (_a2 = resolvedTabs[0]) == null ? void 0 : _a2.value) != null ? _b2 : "matched");
|
|
1565
|
+
}
|
|
1566
|
+
if (controlledSelectedSort == null) setInternalSelectedSort(DEFAULT_EVENT_LIST_SORT);
|
|
1567
|
+
if (!isDiscoveryFiltersEnabled) return;
|
|
1568
|
+
if (controlledCategoryPath == null) setInternalCategoryPath([]);
|
|
1569
|
+
setCollapsedCategoryIds(/* @__PURE__ */ new Set());
|
|
1570
|
+
}, [
|
|
1571
|
+
baseCategoryId,
|
|
1572
|
+
controlledActiveVenueTab,
|
|
1573
|
+
controlledCategoryPath,
|
|
1574
|
+
controlledSelectedSort,
|
|
1575
|
+
isDiscoveryFiltersEnabled,
|
|
1576
|
+
resolvedTabs
|
|
1577
|
+
]);
|
|
1578
|
+
const { categories: topLevelCategories } = useCategories({
|
|
1579
|
+
queryKeyScope: "event-list-top-categories",
|
|
1580
|
+
enabled: isDiscoveryFiltersEnabled,
|
|
1581
|
+
limit: 100
|
|
1582
|
+
});
|
|
1583
|
+
const sortedTopLevelCategories = useMemo4(() => {
|
|
1584
|
+
return sortCategoriesForNavigation(topLevelCategories);
|
|
1585
|
+
}, [topLevelCategories]);
|
|
1586
|
+
const baseCategoryChildPrefetchIds = useMemo4(() => {
|
|
1587
|
+
return Array.from(
|
|
1588
|
+
/* @__PURE__ */ new Set([
|
|
1589
|
+
...baseCategoryId ? [baseCategoryId] : [],
|
|
1590
|
+
...sortedTopLevelCategories.map((category) => category.id),
|
|
1591
|
+
...categoryPath.map((category) => category.id)
|
|
1592
|
+
])
|
|
1593
|
+
);
|
|
1594
|
+
}, [baseCategoryId, categoryPath, sortedTopLevelCategories]);
|
|
1595
|
+
const { childrenByParentId: baseChildrenByParentId, isLoading: isBaseCategoryChildrenLoading } = useCategoryChildren({
|
|
1596
|
+
queryKeyScope: "event-list-category-children",
|
|
1597
|
+
enabled: isDiscoveryFiltersEnabled,
|
|
1598
|
+
parentIds: baseCategoryChildPrefetchIds,
|
|
1599
|
+
limit: 100
|
|
1600
|
+
});
|
|
1601
|
+
const visibleChildPrefetchIds = useMemo4(() => {
|
|
1602
|
+
var _a2, _b2;
|
|
1603
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1604
|
+
if (baseCategoryId) {
|
|
1605
|
+
for (const child of (_a2 = baseChildrenByParentId.get(baseCategoryId)) != null ? _a2 : []) {
|
|
1606
|
+
ids.add(child.id);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
for (const expandedCategory of categoryPath) {
|
|
1610
|
+
for (const childCategory of (_b2 = baseChildrenByParentId.get(expandedCategory.id)) != null ? _b2 : []) {
|
|
1611
|
+
ids.add(childCategory.id);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
return Array.from(ids);
|
|
1615
|
+
}, [baseCategoryId, baseChildrenByParentId, categoryPath]);
|
|
1616
|
+
const { childrenByParentId: visibleChildrenByParentId } = useCategoryChildren({
|
|
1617
|
+
queryKeyScope: "event-list-category-children",
|
|
1618
|
+
enabled: isDiscoveryFiltersEnabled,
|
|
1619
|
+
parentIds: visibleChildPrefetchIds,
|
|
1620
|
+
limit: 100
|
|
1621
|
+
});
|
|
1622
|
+
const visibleGrandchildPrefetchIds = useMemo4(() => {
|
|
1623
|
+
var _a2;
|
|
1624
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1625
|
+
for (const expandedCategory of categoryPath) {
|
|
1626
|
+
for (const childCategory of (_a2 = visibleChildrenByParentId.get(expandedCategory.id)) != null ? _a2 : []) {
|
|
1627
|
+
ids.add(childCategory.id);
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
return Array.from(ids);
|
|
1631
|
+
}, [categoryPath, visibleChildrenByParentId]);
|
|
1632
|
+
const { childrenByParentId: visibleGrandchildrenByParentId } = useCategoryChildren({
|
|
1633
|
+
queryKeyScope: "event-list-category-children",
|
|
1634
|
+
enabled: isDiscoveryFiltersEnabled,
|
|
1635
|
+
parentIds: visibleGrandchildPrefetchIds,
|
|
1636
|
+
limit: 100
|
|
1637
|
+
});
|
|
1638
|
+
const childrenByParentId = useMemo4(() => {
|
|
1639
|
+
return new Map([
|
|
1640
|
+
...baseChildrenByParentId,
|
|
1641
|
+
...visibleChildrenByParentId,
|
|
1642
|
+
...visibleGrandchildrenByParentId
|
|
1643
|
+
]);
|
|
1644
|
+
}, [baseChildrenByParentId, visibleChildrenByParentId, visibleGrandchildrenByParentId]);
|
|
1645
|
+
const controlledCategoryPathKey = (_d = controlledCategoryPath == null ? void 0 : controlledCategoryPath.map((entry) => entry.id).join(",")) != null ? _d : "";
|
|
1646
|
+
const controlledCategoryPathValidationKey = `${baseCategoryId != null ? baseCategoryId : ""}|${controlledCategoryPathKey}`;
|
|
1647
|
+
const [validatedCategoryPathKey, setValidatedCategoryPathKey] = useState3(
|
|
1648
|
+
() => controlledCategoryPath == null || controlledCategoryPath.length === 0 ? controlledCategoryPathValidationKey : ""
|
|
1649
|
+
);
|
|
1650
|
+
useEffect3(() => {
|
|
1651
|
+
if (controlledCategoryPath == null || controlledCategoryPath.length === 0) {
|
|
1652
|
+
setValidatedCategoryPathKey(controlledCategoryPathValidationKey);
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
if (isBaseCategoryChildrenLoading) return;
|
|
1656
|
+
const requestedIds = controlledCategoryPath.map((entry) => entry.id);
|
|
1657
|
+
const validIds = validateSubcategoryPath(requestedIds, baseCategoryId, baseChildrenByParentId);
|
|
1658
|
+
if (validIds.length !== requestedIds.length) {
|
|
1659
|
+
handleCategoryPathChange(controlledCategoryPath.slice(0, validIds.length), {
|
|
1660
|
+
history: "replace"
|
|
1661
|
+
});
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1664
|
+
setValidatedCategoryPathKey(controlledCategoryPathValidationKey);
|
|
1665
|
+
}, [
|
|
1666
|
+
baseCategoryId,
|
|
1667
|
+
baseChildrenByParentId,
|
|
1668
|
+
controlledCategoryPath,
|
|
1669
|
+
controlledCategoryPathKey,
|
|
1670
|
+
controlledCategoryPathValidationKey,
|
|
1671
|
+
handleCategoryPathChange,
|
|
1672
|
+
isBaseCategoryChildrenLoading
|
|
1673
|
+
]);
|
|
1674
|
+
const shouldRenderSubcategoryFilters = isDiscoveryFiltersEnabled && baseCategoryId !== null && (((_f = (_e = childrenByParentId.get(baseCategoryId)) == null ? void 0 : _e.length) != null ? _f : 0) > 0 || categoryPath.length > 0);
|
|
1675
|
+
const baseCategoryEventCount = useMemo4(() => {
|
|
1676
|
+
var _a2, _b2;
|
|
1677
|
+
return (_b2 = (_a2 = sortedTopLevelCategories.find((c) => c.id === baseCategoryId)) == null ? void 0 : _a2.eventCount) != null ? _b2 : 0;
|
|
1678
|
+
}, [baseCategoryId, sortedTopLevelCategories]);
|
|
1679
|
+
const resolvedCategoryIds = useMemo4(() => {
|
|
1680
|
+
if (!isDiscoveryFiltersEnabled) return categoryIds;
|
|
1681
|
+
return resolveCategoryIdsFromPath(categoryPath, baseCategoryId ? [baseCategoryId] : void 0);
|
|
1682
|
+
}, [baseCategoryId, categoryIds, categoryPath, isDiscoveryFiltersEnabled]);
|
|
1683
|
+
const sortQueryParams = useMemo4(() => {
|
|
1684
|
+
return resolveSortQueryParams(selectedSort);
|
|
1685
|
+
}, [selectedSort]);
|
|
1686
|
+
const activeTab = useMemo4(() => {
|
|
1687
|
+
return resolvedTabs.find((tab) => tab.value === activeTabValue);
|
|
1688
|
+
}, [activeTabValue, resolvedTabs]);
|
|
1689
|
+
const venues = useMemo4(() => {
|
|
1690
|
+
return resolveTabVenus(activeTab, visibleVenues);
|
|
1691
|
+
}, [activeTab, visibleVenues]);
|
|
1692
|
+
const matchStatus = useMemo4(() => {
|
|
1693
|
+
return activeTabValue === "matched" ? activeTab == null ? void 0 : activeTab.matchStatus : void 0;
|
|
1694
|
+
}, [activeTabValue, activeTab]);
|
|
1695
|
+
const resolvedMaxVisibleItems = useMemo4(() => {
|
|
1696
|
+
if (!Number.isFinite(maxVisibleItems)) return void 0;
|
|
1697
|
+
return Math.max(1, Math.floor(maxVisibleItems));
|
|
1698
|
+
}, [maxVisibleItems]);
|
|
1699
|
+
const requestLimit = resolvedMaxVisibleItems != null ? resolvedMaxVisibleItems : limit;
|
|
1700
|
+
const shouldPaginate = resolvedMaxVisibleItems == null;
|
|
1701
|
+
const endDateFrom = useMemo4(() => {
|
|
1702
|
+
if (search) return void 0;
|
|
1703
|
+
const BUCKET_MINUTES = 5;
|
|
1704
|
+
const bucket = /* @__PURE__ */ new Date();
|
|
1705
|
+
bucket.setMinutes(Math.floor(bucket.getMinutes() / BUCKET_MINUTES) * BUCKET_MINUTES, 0, 0);
|
|
1706
|
+
return bucket.toISOString();
|
|
1707
|
+
}, [search]);
|
|
1708
|
+
const {
|
|
1709
|
+
events,
|
|
1710
|
+
isLoading,
|
|
1711
|
+
isError,
|
|
1712
|
+
fetchNextPage,
|
|
1713
|
+
hasNextPage,
|
|
1714
|
+
isFetchingNextPage,
|
|
1715
|
+
isPlaceholderData,
|
|
1716
|
+
loadedPageCount
|
|
1717
|
+
} = useVenueEvents({
|
|
1718
|
+
queryKeyScope: "event-list",
|
|
1719
|
+
venues,
|
|
1720
|
+
search,
|
|
1721
|
+
categoryIds: resolvedCategoryIds,
|
|
1722
|
+
matchStatus,
|
|
1723
|
+
limit: requestLimit,
|
|
1724
|
+
status: [MarketStatus.open],
|
|
1725
|
+
sortBy: sortQueryParams.sortBy,
|
|
1726
|
+
sortDir: sortQueryParams.sortDir,
|
|
1727
|
+
endDateFrom,
|
|
1728
|
+
// Fold same-venue companion events into one tile per game when the sports
|
|
1729
|
+
// markets experience is enabled (the sports event-detail view loads the
|
|
1730
|
+
// folded companions via aggKey). Gated on the same flag as that view.
|
|
1731
|
+
grouped: showSportsMarkets,
|
|
1732
|
+
initialPages: initialLoadedPageCount,
|
|
1733
|
+
enabled: controlledCategoryPath == null || validatedCategoryPathKey === controlledCategoryPathValidationKey
|
|
1734
|
+
});
|
|
1735
|
+
useEffect3(() => {
|
|
1736
|
+
if (stateRef) {
|
|
1737
|
+
stateRef.current = { venueTab: activeTabValue, loadedPageCount };
|
|
1738
|
+
}
|
|
1739
|
+
}, [stateRef, activeTabValue, loadedPageCount]);
|
|
1740
|
+
const filteredEvents = useMemo4(() => {
|
|
1741
|
+
return filterEventsByTabValue(events, activeTabValue);
|
|
1742
|
+
}, [events, activeTabValue]);
|
|
1743
|
+
const groupedEvents = useMemo4(() => {
|
|
1744
|
+
return splitEventsByLifecycle(filteredEvents);
|
|
1745
|
+
}, [filteredEvents]);
|
|
1746
|
+
const orderedEvents = useMemo4(() => {
|
|
1747
|
+
return groupedEvents.open;
|
|
1748
|
+
}, [groupedEvents.open]);
|
|
1749
|
+
const tileEvents = useMemo4(() => {
|
|
1750
|
+
const normalizedEvents = orderedEvents.map((event) => mapEventToEventListItemEvent(event)).filter((event) => event != null);
|
|
1751
|
+
if (resolvedMaxVisibleItems == null) return normalizedEvents;
|
|
1752
|
+
return normalizedEvents.slice(0, resolvedMaxVisibleItems);
|
|
1753
|
+
}, [orderedEvents, resolvedMaxVisibleItems]);
|
|
1754
|
+
const visibleVenueMarkets = useMemo4(() => {
|
|
1755
|
+
return collectEventListVenueMarkets(tileEvents);
|
|
1756
|
+
}, [tileEvents]);
|
|
1757
|
+
const visibleMidpointVenueMarketIds = useMemo4(() => {
|
|
1758
|
+
return collectMidpointVenueMarketIds(visibleVenueMarkets);
|
|
1759
|
+
}, [visibleVenueMarkets]);
|
|
1760
|
+
const { midpointRows: sharedMidpointRows, isLoading: isSharedMidpointsLoading } = useVenueMarketMidpoints2({
|
|
1761
|
+
venueMarketIds: visibleMidpointVenueMarketIds,
|
|
1762
|
+
enabled: visibleMidpointVenueMarketIds.length > 0
|
|
1763
|
+
});
|
|
1764
|
+
const shouldRenderLoadingState = isLoading && !isPlaceholderData && tileEvents.length === 0;
|
|
1765
|
+
const shouldRenderEmptyState = !isLoading && !isError && tileEvents.length === 0;
|
|
1766
|
+
const placeholderSkeletonCount = isPlaceholderData ? Math.min(Math.max(tileEvents.length, PLACEHOLDER_SKELETON_MIN_ITEMS), requestLimit) : 0;
|
|
1767
|
+
const shouldRenderPaginationLoadingItems = shouldPaginate && hasNextPage && !isPlaceholderData;
|
|
1768
|
+
const loadMoreRef = useRef3(null);
|
|
1769
|
+
useEffect3(() => {
|
|
1770
|
+
if (!shouldPaginate) return;
|
|
1771
|
+
if (!hasNextPage) return;
|
|
1772
|
+
if (typeof IntersectionObserver === "undefined") return;
|
|
1773
|
+
const target = loadMoreRef.current;
|
|
1774
|
+
if (!target) return;
|
|
1775
|
+
const observer = new IntersectionObserver(
|
|
1776
|
+
(entries) => {
|
|
1777
|
+
const entry = entries[0];
|
|
1778
|
+
if (!(entry == null ? void 0 : entry.isIntersecting)) return;
|
|
1779
|
+
if (isLoading || isFetchingNextPage || !hasNextPage) return;
|
|
1780
|
+
void fetchNextPage();
|
|
1781
|
+
},
|
|
1782
|
+
{
|
|
1783
|
+
rootMargin: "320px 0px"
|
|
1784
|
+
}
|
|
1785
|
+
);
|
|
1786
|
+
observer.observe(target);
|
|
1787
|
+
return () => {
|
|
1788
|
+
observer.disconnect();
|
|
1789
|
+
};
|
|
1790
|
+
}, [fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, shouldPaginate]);
|
|
1791
|
+
const gridClassName = cn(
|
|
1792
|
+
"grid grid-cols-[repeat(auto-fill,minmax(240px,1fr))] md:grid-cols-[repeat(auto-fill,minmax(360px,1fr))] gap-4"
|
|
1793
|
+
);
|
|
1794
|
+
const handleSelectAllCategories = () => {
|
|
1795
|
+
handleCategoryPathChange([], { history: "push" });
|
|
1796
|
+
setCollapsedCategoryIds(/* @__PURE__ */ new Set());
|
|
1797
|
+
onCategoryRootChange == null ? void 0 : onCategoryRootChange(baseCategoryId != null ? baseCategoryId : void 0);
|
|
1798
|
+
setIsSubcategoriesModalOpen(false);
|
|
1799
|
+
};
|
|
1800
|
+
const handleToggleSubcategory = ({
|
|
1801
|
+
entry,
|
|
1802
|
+
depth,
|
|
1803
|
+
hasKnownChildren,
|
|
1804
|
+
isExpanded,
|
|
1805
|
+
isSelected
|
|
1806
|
+
}) => {
|
|
1807
|
+
handleCategoryPathChange([...categoryPath.slice(0, depth), entry], { history: "push" });
|
|
1808
|
+
setCollapsedCategoryIds((prev) => {
|
|
1809
|
+
const next = new Set(prev);
|
|
1810
|
+
if (hasKnownChildren && isExpanded && isSelected) {
|
|
1811
|
+
next.add(entry.id);
|
|
1812
|
+
return next;
|
|
1813
|
+
}
|
|
1814
|
+
next.delete(entry.id);
|
|
1815
|
+
return next;
|
|
1816
|
+
});
|
|
1817
|
+
onCategoryRootChange == null ? void 0 : onCategoryRootChange(baseCategoryId != null ? baseCategoryId : void 0);
|
|
1818
|
+
};
|
|
1819
|
+
if (shouldRenderLoadingState) {
|
|
1820
|
+
return /* @__PURE__ */ jsx4(
|
|
1821
|
+
Skeleton,
|
|
1822
|
+
{
|
|
1823
|
+
view: "event-list",
|
|
1824
|
+
ariaLabel: labels.eventList.loading(title),
|
|
1825
|
+
withSidebar: shouldRenderSubcategoryFilters
|
|
1826
|
+
}
|
|
1827
|
+
);
|
|
1828
|
+
}
|
|
1829
|
+
return /* @__PURE__ */ jsxs3("section", { className: "agg-event-list flex w-full flex-col gap-2 md:gap-5 t", children: [
|
|
1830
|
+
/* @__PURE__ */ jsxs3(
|
|
1831
|
+
"header",
|
|
1832
|
+
{
|
|
1833
|
+
className: cn(
|
|
1834
|
+
"agg-event-list-header",
|
|
1835
|
+
"flex flex-col w-full items-start justify-between",
|
|
1836
|
+
"gap-2 sm:flex-row sm:items-center sm:gap-4"
|
|
1837
|
+
),
|
|
1838
|
+
children: [
|
|
1839
|
+
/* @__PURE__ */ jsx4("div", { className: "agg-event-list-title min-w-32", children: /* @__PURE__ */ jsx4(Typography, { as: "h2", variant: "title", className: "truncate first-letter:uppercase", children: title }) }),
|
|
1840
|
+
/* @__PURE__ */ jsxs3("div", { className: "hidden min-w-0 max-w-full items-center gap-3 md:flex", children: [
|
|
1841
|
+
/* @__PURE__ */ jsx4(
|
|
1842
|
+
EventListTabs,
|
|
1843
|
+
{
|
|
1844
|
+
ariaLabel: labels.eventList.tabsAria(title),
|
|
1845
|
+
className: "agg-event-list-tabs min-w-0 flex-1 max-w-[600px]!",
|
|
1846
|
+
activeTab: activeTabValue,
|
|
1847
|
+
onTabChange: handleActiveTabChange,
|
|
1848
|
+
overflowBehavior: "scroll"
|
|
1849
|
+
}
|
|
1850
|
+
),
|
|
1851
|
+
/* @__PURE__ */ jsx4(
|
|
1852
|
+
Select,
|
|
1853
|
+
{
|
|
1854
|
+
ariaLabel: labels.eventList.sortByLabel,
|
|
1855
|
+
className: "min-w-[200px] w-auto! shrink-0",
|
|
1856
|
+
value: selectedSort,
|
|
1857
|
+
onChange: handleSelectedSortChange,
|
|
1858
|
+
items: sortItems,
|
|
1859
|
+
contentClassName: "py-2",
|
|
1860
|
+
triggerClassName: "rounded-agg-lg!"
|
|
1861
|
+
}
|
|
1862
|
+
)
|
|
1863
|
+
] })
|
|
1864
|
+
]
|
|
1865
|
+
}
|
|
1866
|
+
),
|
|
1867
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex w-full gap-2 md:hidden mb-3", children: [
|
|
1868
|
+
/* @__PURE__ */ jsx4(
|
|
1869
|
+
EventListTabs,
|
|
1870
|
+
{
|
|
1871
|
+
ariaLabel: labels.eventList.tabsAria(title),
|
|
1872
|
+
className: "agg-event-list-tabs min-w-0 flex-1",
|
|
1873
|
+
activeTab: activeTabValue,
|
|
1874
|
+
onTabChange: handleActiveTabChange,
|
|
1875
|
+
overflowBehavior: "select"
|
|
1876
|
+
}
|
|
1877
|
+
),
|
|
1878
|
+
/* @__PURE__ */ jsx4(
|
|
1879
|
+
Select,
|
|
1880
|
+
{
|
|
1881
|
+
ariaLabel: labels.eventList.sortByLabel,
|
|
1882
|
+
className: "min-w-0 flex-1 md:min-w-[144px]",
|
|
1883
|
+
value: selectedSort,
|
|
1884
|
+
onChange: handleSelectedSortChange,
|
|
1885
|
+
items: sortItems,
|
|
1886
|
+
contentClassName: "rounded-[12px] py-2 shadow-[0_8px_16px_rgba(0,0,0,0.1)]"
|
|
1887
|
+
}
|
|
1888
|
+
),
|
|
1889
|
+
shouldRenderSubcategoryFilters ? /* @__PURE__ */ jsx4(
|
|
1890
|
+
"button",
|
|
1891
|
+
{
|
|
1892
|
+
type: "button",
|
|
1893
|
+
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-[8px] border-2 border-agg-primary bg-agg-secondary text-agg-foreground cursor-pointer",
|
|
1894
|
+
"aria-label": labels.eventList.subcategoriesOpenAria,
|
|
1895
|
+
onClick: () => setIsSubcategoriesModalOpen(true),
|
|
1896
|
+
children: /* @__PURE__ */ jsx4(Icon, { name: "apps", size: "small", color: "currentColor" })
|
|
1897
|
+
}
|
|
1898
|
+
) : null
|
|
1899
|
+
] }),
|
|
1900
|
+
/* @__PURE__ */ jsxs3(
|
|
1901
|
+
"div",
|
|
1902
|
+
{
|
|
1903
|
+
className: cn("flex w-full gap-6", shouldRenderSubcategoryFilters ? "md:items-start" : ""),
|
|
1904
|
+
children: [
|
|
1905
|
+
shouldRenderSubcategoryFilters ? /* @__PURE__ */ jsx4("aside", { className: "hidden w-[200px] shrink-0 md:block self-start sticky top-4", children: /* @__PURE__ */ jsx4("div", { className: "agg-sidebar max-h-[calc(100vh-19rem)] overflow-y-auto rounded-[8px] border border-agg-separator bg-agg-secondary p-2", children: /* @__PURE__ */ jsx4(
|
|
1906
|
+
CategorySidebar,
|
|
1907
|
+
{
|
|
1908
|
+
baseCategoryId,
|
|
1909
|
+
childrenByParentId,
|
|
1910
|
+
categoryPath,
|
|
1911
|
+
collapsedCategoryIds,
|
|
1912
|
+
totalEventCount: baseCategoryEventCount,
|
|
1913
|
+
labels: { subcategoriesAll: labels.eventList.subcategoriesAll },
|
|
1914
|
+
onSelectAll: handleSelectAllCategories,
|
|
1915
|
+
onToggleCategory: handleToggleSubcategory
|
|
1916
|
+
}
|
|
1917
|
+
) }) }) : null,
|
|
1918
|
+
/* @__PURE__ */ jsxs3(
|
|
1919
|
+
"div",
|
|
1920
|
+
{
|
|
1921
|
+
className: cn(
|
|
1922
|
+
"agg-event-list-grid",
|
|
1923
|
+
"grid grid-cols-[repeat(auto-fill,minmax(240px,1fr))] md:grid-cols-[repeat(auto-fill,minmax(360px,1fr))] gap-4",
|
|
1924
|
+
"w-full",
|
|
1925
|
+
gridClassName
|
|
1926
|
+
),
|
|
1927
|
+
children: [
|
|
1928
|
+
isPlaceholderData ? Array.from({ length: placeholderSkeletonCount }).map((_, index) => /* @__PURE__ */ jsx4(
|
|
1929
|
+
EventListItem,
|
|
1930
|
+
{
|
|
1931
|
+
isLoading: true,
|
|
1932
|
+
classNames: {
|
|
1933
|
+
root: "agg-event-list-item w-full min-w-0! max-w-none justify-between!"
|
|
1934
|
+
}
|
|
1935
|
+
},
|
|
1936
|
+
`placeholder-${index}`
|
|
1937
|
+
)) : null,
|
|
1938
|
+
(isPlaceholderData ? [] : tileEvents).map((event) => /* @__PURE__ */ jsx4(
|
|
1939
|
+
EventListItem,
|
|
1940
|
+
{
|
|
1941
|
+
event,
|
|
1942
|
+
midpointRows: sharedMidpointRows,
|
|
1943
|
+
midpointsLoading: isSharedMidpointsLoading,
|
|
1944
|
+
classNames: {
|
|
1945
|
+
root: "agg-event-list-item w-full min-w-0! max-w-none justify-between!"
|
|
1946
|
+
},
|
|
1947
|
+
onEventClick,
|
|
1948
|
+
onMarketClick,
|
|
1949
|
+
getMarketHref,
|
|
1950
|
+
href: getEventHref == null ? void 0 : getEventHref(event),
|
|
1951
|
+
marketStatus: MarketStatus.open
|
|
1952
|
+
},
|
|
1953
|
+
event.id
|
|
1954
|
+
)),
|
|
1955
|
+
shouldRenderPaginationLoadingItems ? Array.from({ length: 6 }).map((_, index) => /* @__PURE__ */ jsx4(
|
|
1956
|
+
EventListItem,
|
|
1957
|
+
{
|
|
1958
|
+
isLoading: true,
|
|
1959
|
+
classNames: {
|
|
1960
|
+
root: "agg-event-list-item w-full min-w-0! max-w-none justify-between!"
|
|
1961
|
+
}
|
|
1962
|
+
},
|
|
1963
|
+
`loading-${index}`
|
|
1964
|
+
)) : null,
|
|
1965
|
+
shouldRenderEmptyState ? /* @__PURE__ */ jsx4("div", { className: "col-span-full w-full", children: /* @__PURE__ */ jsx4(
|
|
1966
|
+
StateMessage,
|
|
1967
|
+
{
|
|
1968
|
+
title: labels.eventList.emptyTitle,
|
|
1969
|
+
description: labels.eventList.emptyDescription,
|
|
1970
|
+
icon: /* @__PURE__ */ jsx4(Icon, { name: "search-empty" })
|
|
1971
|
+
}
|
|
1972
|
+
) }) : null,
|
|
1973
|
+
isError ? /* @__PURE__ */ jsx4("div", { className: "col-span-full w-full", children: /* @__PURE__ */ jsx4(
|
|
1974
|
+
StateMessage,
|
|
1975
|
+
{
|
|
1976
|
+
title: labels.eventList.errorTitle,
|
|
1977
|
+
description: labels.eventList.errorDescription,
|
|
1978
|
+
icon: /* @__PURE__ */ jsx4(Icon, { name: "warning" })
|
|
1979
|
+
}
|
|
1980
|
+
) }) : null
|
|
1981
|
+
]
|
|
1982
|
+
}
|
|
1983
|
+
)
|
|
1984
|
+
]
|
|
1985
|
+
}
|
|
1986
|
+
),
|
|
1987
|
+
shouldRenderSubcategoryFilters ? /* @__PURE__ */ jsx4(Modal, { open: isSubcategoriesModalOpen, onOpenChange: setIsSubcategoriesModalOpen, children: /* @__PURE__ */ jsx4(
|
|
1988
|
+
Modal.Container,
|
|
1989
|
+
{
|
|
1990
|
+
classNames: {
|
|
1991
|
+
// pointer-events-none lets clicks on the empty area above the panel pass through
|
|
1992
|
+
// to Dialog.Overlay, which triggers Radix's outside-click dismiss.
|
|
1993
|
+
content: "items-end p-0 pointer-events-none",
|
|
1994
|
+
container: "w-full max-w-none border-0 bg-transparent shadow-none"
|
|
1995
|
+
},
|
|
1996
|
+
children: /* @__PURE__ */ jsxs3("div", { className: "pointer-events-auto w-full rounded-t-[12px] border border-agg-separator bg-agg-secondary", children: [
|
|
1997
|
+
/* @__PURE__ */ jsx4("div", { className: "flex justify-center pb-1 pt-3", "aria-hidden": "true", children: /* @__PURE__ */ jsx4("div", { className: "h-1 w-10 rounded-full bg-agg-muted-foreground/30" }) }),
|
|
1998
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between px-4 pb-2 pt-1", children: [
|
|
1999
|
+
/* @__PURE__ */ jsx4(Dialog.Title, { className: "text-agg-sm font-agg-bold leading-agg-5 text-agg-foreground", children: labels.eventList.subcategoriesLabel }),
|
|
2000
|
+
/* @__PURE__ */ jsx4(
|
|
2001
|
+
Dialog.Close,
|
|
2002
|
+
{
|
|
2003
|
+
className: "flex cursor-pointer items-center justify-center rounded-full p-1 text-agg-muted-foreground hover:bg-agg-secondary-hover",
|
|
2004
|
+
"aria-label": labels.common.close,
|
|
2005
|
+
children: /* @__PURE__ */ jsx4(CloseIcon, { className: "h-5 w-5" })
|
|
2006
|
+
}
|
|
2007
|
+
)
|
|
2008
|
+
] }),
|
|
2009
|
+
/* @__PURE__ */ jsx4("div", { className: "flex flex-col gap-1 px-4 pb-4", children: /* @__PURE__ */ jsx4(
|
|
2010
|
+
CategorySidebar,
|
|
2011
|
+
{
|
|
2012
|
+
baseCategoryId,
|
|
2013
|
+
childrenByParentId,
|
|
2014
|
+
categoryPath,
|
|
2015
|
+
collapsedCategoryIds,
|
|
2016
|
+
totalEventCount: baseCategoryEventCount,
|
|
2017
|
+
labels: { subcategoriesAll: labels.eventList.subcategoriesAll },
|
|
2018
|
+
onSelectAll: handleSelectAllCategories,
|
|
2019
|
+
onToggleCategory: handleToggleSubcategory
|
|
2020
|
+
}
|
|
2021
|
+
) })
|
|
2022
|
+
] })
|
|
2023
|
+
}
|
|
2024
|
+
) }) : null,
|
|
2025
|
+
shouldPaginate && hasNextPage ? /* @__PURE__ */ jsx4("div", { ref: loadMoreRef, className: "agg-event-list-sentinel h-px w-full", "aria-hidden": true }) : null
|
|
2026
|
+
] });
|
|
2027
|
+
};
|
|
2028
|
+
EventList.displayName = "EventList";
|
|
2029
|
+
|
|
2030
|
+
export {
|
|
2031
|
+
EventListItem,
|
|
2032
|
+
EventListItemV2,
|
|
2033
|
+
DEFAULT_EVENTS_LIMIT,
|
|
2034
|
+
DEFAULT_EVENT_LIST_SORT,
|
|
2035
|
+
EVENT_LIST_SORT_VALUES,
|
|
2036
|
+
useEventListTabs,
|
|
2037
|
+
EventListTabs,
|
|
2038
|
+
useEventListTabsHeaderOverflow,
|
|
2039
|
+
EventList
|
|
2040
|
+
};
|