@agg-build/ui 4.18.1 → 4.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +1 -0
  2. package/dist/{chunk-ZNOAKSPT.mjs → chunk-47CCGQH6.mjs} +2 -2
  3. package/dist/{chunk-2OBJ7DYT.mjs → chunk-5YHKIJ23.mjs} +21 -10
  4. package/dist/{chunk-2UPO6G3S.mjs → chunk-DWPBGMVJ.mjs} +50 -6
  5. package/dist/{chunk-VUZ72Q7H.mjs → chunk-DXASFSVL.mjs} +3 -2
  6. package/dist/{chunk-YXMDEUHP.mjs → chunk-GT3DCFIT.mjs} +494 -41
  7. package/dist/{chunk-HFL3CEWG.mjs → chunk-NSQQ62QK.mjs} +4 -4
  8. package/dist/{chunk-NRPS2D3Q.mjs → chunk-ROA5K67W.mjs} +1 -1
  9. package/dist/{chunk-JJ3VVCEP.mjs → chunk-WOCZ4TVT.mjs} +12 -8
  10. package/dist/{chunk-WIGSRHUG.mjs → chunk-XZVGHKMW.mjs} +3 -2
  11. package/dist/{event-market-GX24AP2H.mjs → event-market-2BAMDM5I.mjs} +6 -6
  12. package/dist/events.js +60 -11
  13. package/dist/events.mjs +4 -4
  14. package/dist/index.js +1148 -621
  15. package/dist/index.mjs +17 -9
  16. package/dist/modals.js +3 -2
  17. package/dist/modals.mjs +3 -3
  18. package/dist/pages.js +580 -53
  19. package/dist/pages.mjs +16 -8
  20. package/dist/primitives.js +3 -2
  21. package/dist/primitives.mjs +1 -1
  22. package/dist/styles.css +1 -1
  23. package/dist/tailwind.css +1 -1
  24. package/dist/trading.js +21 -9
  25. package/dist/trading.mjs +4 -4
  26. package/dist/types/pages/index.d.mts +1 -0
  27. package/dist/types/pages/index.d.ts +1 -0
  28. package/dist/types/pages/leaderboard/components/leaderboard-header-row.d.mts +7 -0
  29. package/dist/types/pages/leaderboard/components/leaderboard-header-row.d.ts +7 -0
  30. package/dist/types/pages/leaderboard/components/leaderboard-row.d.mts +7 -0
  31. package/dist/types/pages/leaderboard/components/leaderboard-row.d.ts +7 -0
  32. package/dist/types/pages/leaderboard/components/leaderboard-skeleton.d.mts +3 -0
  33. package/dist/types/pages/leaderboard/components/leaderboard-skeleton.d.ts +3 -0
  34. package/dist/types/pages/leaderboard/components/segmented-control.d.mts +18 -0
  35. package/dist/types/pages/leaderboard/components/segmented-control.d.ts +18 -0
  36. package/dist/types/pages/leaderboard/index.d.mts +28 -0
  37. package/dist/types/pages/leaderboard/index.d.ts +28 -0
  38. package/dist/types/pages/leaderboard/leaderboard.constants.d.mts +8 -0
  39. package/dist/types/pages/leaderboard/leaderboard.constants.d.ts +8 -0
  40. package/dist/types/pages/leaderboard/leaderboard.types.d.mts +11 -0
  41. package/dist/types/pages/leaderboard/leaderboard.types.d.ts +11 -0
  42. package/dist/types/pages/user-profile/position-view-model.d.mts +2 -4
  43. package/dist/types/pages/user-profile/position-view-model.d.ts +2 -4
  44. package/dist/types/primitives/remote-image/index.d.mts +1 -1
  45. package/dist/types/primitives/remote-image/index.d.ts +1 -1
  46. package/dist/types/primitives/remote-image/remote-image.types.d.mts +6 -0
  47. package/dist/types/primitives/remote-image/remote-image.types.d.ts +6 -0
  48. package/dist/types/shared/pnl-format.d.mts +20 -0
  49. package/dist/types/shared/pnl-format.d.ts +20 -0
  50. package/package.json +3 -3
  51. /package/dist/types/{pages/user-profile/components → shared}/default-avatar.d.mts +0 -0
  52. /package/dist/types/{pages/user-profile/components → shared}/default-avatar.d.ts +0 -0
package/dist/pages.js CHANGED
@@ -7242,7 +7242,8 @@ var init_remote_image = __esm({
7242
7242
  width,
7243
7243
  height,
7244
7244
  onClick,
7245
- ariaLabel
7245
+ ariaLabel,
7246
+ fallback
7246
7247
  }) => {
7247
7248
  const {
7248
7249
  general: { theme }
@@ -7299,7 +7300,7 @@ var init_remote_image = __esm({
7299
7300
  className: cn(placeholderClasses, classNames == null ? void 0 : classNames.placeholder),
7300
7301
  "aria-hidden": true,
7301
7302
  "aria-errormessage": "Image failed to load",
7302
- children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
7303
+ children: fallback != null ? fallback : /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
7303
7304
  Icon,
7304
7305
  {
7305
7306
  name: "image",
@@ -12899,13 +12900,17 @@ var init_event_list_item_details_utils = __esm({
12899
12900
  nowSec = (0, import_dayjs4.default)().unix(),
12900
12901
  selectedMarket
12901
12902
  }) => {
12902
- var _a, _b;
12903
+ var _a;
12903
12904
  const scopedMarkets = selectedMarket ? [selectedMarket] : event.venueMarkets;
12904
- const preferredEventStart = (_a = toUnixTimestamp(event.startDate)) != null ? _a : toUnixTimestamp(event.creationDate);
12905
- const marketStartCandidates = scopedMarkets.map((market) => {
12906
- var _a2;
12907
- return (_a2 = toUnixTimestamp(market.startDate)) != null ? _a2 : toUnixTimestamp(market.creationDate);
12908
- }).filter((value) => value != null);
12905
+ const resolveHistoryStart = (startDate, creationDate) => {
12906
+ const start = toUnixTimestamp(startDate);
12907
+ if (start != null && start <= nowSec) return start;
12908
+ const created = toUnixTimestamp(creationDate);
12909
+ if (created != null && created <= nowSec) return created;
12910
+ return null;
12911
+ };
12912
+ const preferredEventStart = resolveHistoryStart(event.startDate, event.creationDate);
12913
+ const marketStartCandidates = scopedMarkets.map((market) => resolveHistoryStart(market.startDate, market.creationDate)).filter((value) => value != null);
12909
12914
  const metadataStarts = [preferredEventStart, ...marketStartCandidates].filter(
12910
12915
  (value) => value != null
12911
12916
  );
@@ -12943,7 +12948,7 @@ var init_event_list_item_details_utils = __esm({
12943
12948
  const matchingRange = CHART_RANGE_PRIORITY.find((range) => {
12944
12949
  return RANGE_SECONDS_BY_TIME_RANGE[range] >= requiredSeconds;
12945
12950
  });
12946
- return (_b = matchingRange != null ? matchingRange : fallbackRange) != null ? _b : "ALL";
12951
+ return (_a = matchingRange != null ? matchingRange : fallbackRange) != null ? _a : "ALL";
12947
12952
  };
12948
12953
  matchOutcomeByLabel = (outcome, selectedOutcomeLabel) => {
12949
12954
  const normalizedSelectedLabel = normalizeLabel(selectedOutcomeLabel);
@@ -16649,6 +16654,20 @@ var init_item_details = __esm({
16649
16654
  resolvedEventTradingState.isTradingDisabled ? [] : resolvedEventTradingState.displayMarkets,
16650
16655
  scopedSelectedMarketId
16651
16656
  );
16657
+ const selectedBetdexOutcomes = (0, import_react35.useMemo)(
16658
+ () => eventDetailVenueMarkets.filter((market) => market.venue === "betdex").flatMap(
16659
+ (market) => market.venueMarketOutcomes.map((outcome) => ({
16660
+ venue: market.venue,
16661
+ venueMarketOutcomeId: outcome.id
16662
+ }))
16663
+ ),
16664
+ [eventDetailVenueMarkets]
16665
+ );
16666
+ (0, import_hooks58.useMarketOrderbook)({
16667
+ venueOutcomes: selectedBetdexOutcomes,
16668
+ enabled: !resolvedEventTradingState.isTradingDisabled && selectedBetdexOutcomes.length > 0,
16669
+ live: false
16670
+ });
16652
16671
  const wsLivePrices = (0, import_hooks58.useLiveOutcomePrices)(eventDetailVenueMarkets);
16653
16672
  const wsBestPrices = (0, import_hooks58.useLiveBestPrices)(eventDetailVenueMarkets);
16654
16673
  const resolvedMidpointsResult = midpointsResult != null ? midpointsResult : {
@@ -16786,6 +16805,7 @@ var init_item_details = __esm({
16786
16805
  src: (0, import_hooks58.optimizedImageUrl)(event.image, 60),
16787
16806
  retinaSrc: (0, import_hooks58.retinaImageUrl)(event.image, 60),
16788
16807
  alt: "",
16808
+ fallback: event.venue ? /* @__PURE__ */ (0, import_jsx_runtime159.jsx)(VenueLogo, { venue: event.venue, size: "large" }) : void 0,
16789
16809
  className: "agg-event-image size-10 rounded-agg-lg object-cover md:size-[60px]"
16790
16810
  }
16791
16811
  ),
@@ -16937,7 +16957,7 @@ var init_item_details = __esm({
16937
16957
  selectedOutcomeId: (tradingContext == null ? void 0 : tradingContext.selectedEventId) === event.id ? tradingContext.selectedOutcomeId : (_f = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.venueMarketOutcomes[0]) == null ? void 0 : _f.id,
16938
16958
  eventEndDate: event.endDate,
16939
16959
  contractWindow,
16940
- range: config.chart.selectedChartTimeRange,
16960
+ range: chartRangeOverride != null ? chartRangeOverride : config.chart.selectedChartTimeRange,
16941
16961
  live: !resolvedEventTradingState.isTradingDisabled && config.features.enableLiveUpdates
16942
16962
  },
16943
16963
  event.id
@@ -16987,7 +17007,7 @@ var init_item_details = __esm({
16987
17007
  ) : null,
16988
17008
  !contractWindow ? /* @__PURE__ */ (0, import_jsx_runtime159.jsx)("span", { "aria-hidden": "true", className: "hidden h-4 w-px bg-agg-separator md:block" }) : null,
16989
17009
  !contractWindow && import_hooks58.CHART_TIME_RANGES.map((timeRange) => {
16990
- const effectiveRange = chartView === "all" ? config.chart.selectedChartTimeRange : chartRangeOverride != null ? chartRangeOverride : config.chart.selectedChartTimeRange;
17010
+ const effectiveRange = chartRangeOverride != null ? chartRangeOverride : config.chart.selectedChartTimeRange;
16991
17011
  const isActive = timeRange === effectiveRange;
16992
17012
  return /* @__PURE__ */ (0, import_jsx_runtime159.jsx)(
16993
17013
  Button,
@@ -18572,6 +18592,13 @@ var init_market_details = __esm({
18572
18592
  labels
18573
18593
  });
18574
18594
  }, [config.formatting.formatCompactCurrency, venueMarkets, image, labels, marketId, title2]);
18595
+ const primaryVenue = (0, import_react40.useMemo)(
18596
+ () => {
18597
+ var _a2, _b2;
18598
+ return (_b2 = (_a2 = venueMarkets.find((venueMarket) => venueMarket.id === marketId)) != null ? _a2 : venueMarkets[0]) == null ? void 0 : _b2.venue;
18599
+ },
18600
+ [venueMarkets, marketId]
18601
+ );
18575
18602
  const livePrices = (0, import_react40.useMemo)(() => {
18576
18603
  const merged = /* @__PURE__ */ new Map();
18577
18604
  if (midpointsFallback == null ? void 0 : midpointsFallback.size) {
@@ -18778,6 +18805,26 @@ var init_market_details = __esm({
18778
18805
  });
18779
18806
  }, [model, selectedOutcomeLabel, selectedOutcomeId]);
18780
18807
  const orderBookEnabled = isOpened && effectiveSelectedTab === "order-book" && !marketTradingState.isTradingDisabled;
18808
+ const betdexSeedOutcomes = (0, import_react40.useMemo)(
18809
+ () => {
18810
+ var _a2;
18811
+ return ((_a2 = model == null ? void 0 : model.market.venueMarkets) != null ? _a2 : []).filter((venueMarket) => venueMarket.venue === "betdex").flatMap(
18812
+ (venueMarket) => {
18813
+ var _a3;
18814
+ return ((_a3 = venueMarket.venueMarketOutcomes) != null ? _a3 : []).map((outcome) => ({
18815
+ venue: venueMarket.venue,
18816
+ venueMarketOutcomeId: outcome.id
18817
+ }));
18818
+ }
18819
+ );
18820
+ },
18821
+ [model]
18822
+ );
18823
+ (0, import_hooks62.useMarketOrderbook)({
18824
+ venueOutcomes: betdexSeedOutcomes,
18825
+ enabled: !orderBookEnabled && !marketTradingState.isTradingDisabled && betdexSeedOutcomes.length > 0,
18826
+ live: false
18827
+ });
18781
18828
  const selectedVenueOutcome = selectedOutcomesByVenue.find(
18782
18829
  (item) => item.outcomeId === selectedOutcomeId
18783
18830
  );
@@ -18972,6 +19019,7 @@ var init_market_details = __esm({
18972
19019
  src: (0, import_hooks62.optimizedImageUrl)(model.image, 60),
18973
19020
  retinaSrc: (0, import_hooks62.retinaImageUrl)(model.image, 60),
18974
19021
  alt: "",
19022
+ fallback: primaryVenue ? /* @__PURE__ */ (0, import_jsx_runtime164.jsx)(VenueLogo, { venue: primaryVenue, size: "large" }) : void 0,
18975
19023
  className: "agg-market-image size-12 rounded-agg-lg object-cover md:size-[60px]"
18976
19024
  }
18977
19025
  ) : null,
@@ -22551,7 +22599,7 @@ var init_index_place_order_utils = __esm({
22551
22599
  selectedMarket,
22552
22600
  tradeSide = "buy"
22553
22601
  }) => {
22554
- var _a, _b, _c, _d, _e;
22602
+ var _a, _b, _c, _d, _e, _f;
22555
22603
  if (!selectedMarket) {
22556
22604
  return {
22557
22605
  tone: "warning",
@@ -22571,7 +22619,15 @@ var init_index_place_order_utils = __esm({
22571
22619
  };
22572
22620
  }
22573
22621
  if (quoteData.status === "no_orderbooks") {
22574
- const serverError = (_a = quoteData.error) == null ? void 0 : _a.trim();
22622
+ const warnings = (_a = quoteData.warnings) != null ? _a : [];
22623
+ if (warnings.length > 0 && warnings.every((warning) => warning.reason === "hosted_cash_unavailable")) {
22624
+ return {
22625
+ tone: "warning",
22626
+ message: labels.betdexBalanceUnavailable,
22627
+ placement: "above-action"
22628
+ };
22629
+ }
22630
+ const serverError = (_b = quoteData.error) == null ? void 0 : _b.trim();
22575
22631
  return {
22576
22632
  tone: "error",
22577
22633
  message: serverError || labels.noOrderbooks,
@@ -22588,24 +22644,24 @@ var init_index_place_order_utils = __esm({
22588
22644
  if (quoteData.status === "insufficient_input_amount") {
22589
22645
  return {
22590
22646
  tone: "error",
22591
- message: (_b = quoteData.message) != null ? _b : labels.insufficientInputAmount,
22647
+ message: (_c = quoteData.message) != null ? _c : labels.insufficientInputAmount,
22592
22648
  placement: "above-action"
22593
22649
  };
22594
22650
  }
22595
22651
  if (quoteData.status === "invalid_input") {
22596
22652
  return {
22597
22653
  tone: "error",
22598
- message: (_c = quoteData.message) != null ? _c : labels.quoteUnavailable,
22654
+ message: (_d = quoteData.message) != null ? _d : labels.quoteUnavailable,
22599
22655
  placement: "above-action"
22600
22656
  };
22601
22657
  }
22602
22658
  if (quoteData.status === "insufficient_position") {
22603
- const total = (_d = quoteData.positionAvailability) == null ? void 0 : _d.totalSellableShares;
22659
+ const total = (_e = quoteData.positionAvailability) == null ? void 0 : _e.totalSellableShares;
22604
22660
  const message = total != null ? labels.insufficientPosition(total) : labels.insufficientPositionGeneric;
22605
22661
  return { tone: "error", message, placement: "above-action" };
22606
22662
  }
22607
22663
  if (quoteData.status === "insufficient_depth") {
22608
- const serverError = (_e = quoteData.error) == null ? void 0 : _e.trim();
22664
+ const serverError = (_f = quoteData.error) == null ? void 0 : _f.trim();
22609
22665
  return {
22610
22666
  tone: "error",
22611
22667
  message: tradeSide === "sell" ? serverError || labels.insufficientSellDepth : serverError || labels.insufficientLiquidity,
@@ -25284,6 +25340,7 @@ var init_place_order = __esm({
25284
25340
  headerSubtitle,
25285
25341
  headerImage,
25286
25342
  headerTitle,
25343
+ headerVenue,
25287
25344
  onClose
25288
25345
  }) => {
25289
25346
  if (!headerTitle) return null;
@@ -25294,6 +25351,7 @@ var init_place_order = __esm({
25294
25351
  {
25295
25352
  src: headerImage,
25296
25353
  alt: "",
25354
+ fallback: headerVenue ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(VenueLogo, { venue: headerVenue, size: "large" }) : void 0,
25297
25355
  className: "agg-order-market-image h-12 w-12 shrink-0 overflow-hidden rounded-agg-lg object-cover"
25298
25356
  }
25299
25357
  ),
@@ -25620,7 +25678,7 @@ var init_place_order = __esm({
25620
25678
  showResolvingState = false,
25621
25679
  midpointsResult
25622
25680
  }) => {
25623
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha;
25681
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia;
25624
25682
  const {
25625
25683
  enableDebug: isExecutionDebugEnabled,
25626
25684
  features: { enableAnimations, showFeesBreakdown, showLimitOrders: limitOrdersFeature },
@@ -27906,6 +27964,7 @@ var init_place_order = __esm({
27906
27964
  headerSubtitle,
27907
27965
  headerImage,
27908
27966
  headerTitle,
27967
+ headerVenue: (_ia = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.venue) != null ? _ia : scopedSelectedEvent == null ? void 0 : scopedSelectedEvent.venue,
27909
27968
  onClose
27910
27969
  }),
27911
27970
  /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { className: cn("agg-order-panel-content flex flex-col gap-6", classNames == null ? void 0 : classNames.content), children: [
@@ -32642,6 +32701,10 @@ __export(pages_exports, {
32642
32701
  EventOpenOrders: () => EventOpenOrders,
32643
32702
  EventOpenOrdersCard: () => EventOpenOrdersCard,
32644
32703
  HomePage: () => HomePage,
32704
+ LEADERBOARD_DEFAULT_METRIC: () => LEADERBOARD_DEFAULT_METRIC,
32705
+ LEADERBOARD_DEFAULT_PERIOD: () => LEADERBOARD_DEFAULT_PERIOD,
32706
+ LEADERBOARD_METRICS: () => LEADERBOARD_METRICS,
32707
+ LeaderboardPage: () => LeaderboardPage,
32645
32708
  ManageBalancesModal: () => ManageBalancesModal,
32646
32709
  USER_PROFILE_TAB_ACTIVITY: () => USER_PROFILE_TAB_ACTIVITY,
32647
32710
  USER_PROFILE_TAB_OPEN_ORDERS: () => USER_PROFILE_TAB_OPEN_ORDERS,
@@ -33372,6 +33435,7 @@ var EventListItemContent = ({
33372
33435
  src: (0, import_hooks40.optimizedImageUrl)(resolvedImage, 40),
33373
33436
  retinaSrc: (0, import_hooks40.retinaImageUrl)(resolvedImage, 40),
33374
33437
  alt: "",
33438
+ fallback: event.venue ? /* @__PURE__ */ (0, import_jsx_runtime147.jsx)(VenueLogo, { venue: event.venue, size: "medium" }) : void 0,
33375
33439
  classNames: {
33376
33440
  root: "agg-event-image h-10 w-10 shrink-0 rounded-agg-lg object-cover",
33377
33441
  image: "transition-transform duration-300 group-hover/agg-event-card:scale-110"
@@ -36714,24 +36778,58 @@ var USER_PROFILE_POSITION_FILTERS = [
36714
36778
  { value: "closed", label: "Closed" }
36715
36779
  ];
36716
36780
 
36717
- // src/pages/user-profile/position-view-model.ts
36718
- var defaultLabels2 = {
36719
- avgPrefix: "avg",
36720
- nowPrefix: "now",
36721
- finalPrefix: "final"
36722
- };
36723
- var missingLabel = "\u2014";
36781
+ // src/shared/pnl-format.ts
36782
+ var MISSING_VALUE_LABEL = "\u2014";
36724
36783
  var usdFormatter = new Intl.NumberFormat("en-US", {
36725
36784
  style: "currency",
36726
36785
  currency: "USD",
36727
36786
  minimumFractionDigits: 2,
36728
36787
  maximumFractionDigits: 2
36729
36788
  });
36789
+ var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
36790
+ var formatCurrency = (value, formatCurrencyOverride) => {
36791
+ if (!isFiniteNumber(value)) return MISSING_VALUE_LABEL;
36792
+ if (formatCurrencyOverride) return formatCurrencyOverride(value);
36793
+ return usdFormatter.format(value);
36794
+ };
36795
+ var NEGLIGIBLE_CURRENCY_THRESHOLD = 5e-3;
36796
+ var formatSignedCurrency = (value, formatCurrencyOverride, options = {}) => {
36797
+ if (!isFiniteNumber(value)) return MISSING_VALUE_LABEL;
36798
+ if (value === 0) return formatCurrency(0, formatCurrencyOverride);
36799
+ const sign = value > 0 ? "+" : "-";
36800
+ const magnitude = Math.abs(value);
36801
+ if (options.markNegligible && magnitude < NEGLIGIBLE_CURRENCY_THRESHOLD) {
36802
+ return `${sign}<${formatCurrency(0.01, formatCurrencyOverride)}`;
36803
+ }
36804
+ return `${sign}${formatCurrency(magnitude, formatCurrencyOverride)}`;
36805
+ };
36806
+ var formatCurrencyMarkingNegligible = (value, formatCurrencyOverride) => {
36807
+ if (!isFiniteNumber(value)) return MISSING_VALUE_LABEL;
36808
+ if (value !== 0 && Math.abs(value) < NEGLIGIBLE_CURRENCY_THRESHOLD) {
36809
+ return `<${formatCurrency(0.01, formatCurrencyOverride)}`;
36810
+ }
36811
+ return formatCurrency(value, formatCurrencyOverride);
36812
+ };
36813
+ var getPositionTone = (value) => {
36814
+ if (!isFiniteNumber(value) || value === 0) return "neutral";
36815
+ return value > 0 ? "positive" : "negative";
36816
+ };
36817
+ var toneClassName = (tone) => {
36818
+ if (tone === "positive") return "text-agg-success";
36819
+ if (tone === "negative") return "text-agg-error";
36820
+ return "text-agg-muted-foreground";
36821
+ };
36822
+
36823
+ // src/pages/user-profile/position-view-model.ts
36824
+ var defaultLabels2 = {
36825
+ avgPrefix: "avg",
36826
+ nowPrefix: "now",
36827
+ finalPrefix: "final"
36828
+ };
36730
36829
  var percentFormatter = new Intl.NumberFormat("en-US", {
36731
36830
  minimumFractionDigits: 0,
36732
36831
  maximumFractionDigits: 1
36733
36832
  });
36734
- var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
36735
36833
  var parseCurrencyLabel = (label2) => {
36736
36834
  if (!label2) return null;
36737
36835
  const normalized = label2.replace(/[$,\s]/g, "");
@@ -36752,23 +36850,13 @@ var parsePercentLabel = (label2) => {
36752
36850
  const parsed = Number(match[1].replace(/,/g, ""));
36753
36851
  return Number.isFinite(parsed) ? parsed : null;
36754
36852
  };
36755
- var formatCurrency = (value, formatCurrencyOverride) => {
36756
- if (!isFiniteNumber(value)) return missingLabel;
36757
- if (formatCurrencyOverride) return formatCurrencyOverride(value);
36758
- return usdFormatter.format(value);
36759
- };
36760
- var formatSignedCurrency = (value, formatCurrencyOverride) => {
36761
- if (!isFiniteNumber(value)) return missingLabel;
36762
- if (value === 0) return formatCurrency(0, formatCurrencyOverride);
36763
- return `${value > 0 ? "+" : "-"}${formatCurrency(Math.abs(value), formatCurrencyOverride)}`;
36764
- };
36765
36853
  var formatPriceCents2 = (value, formatPrice) => {
36766
- if (!isFiniteNumber(value)) return missingLabel;
36854
+ if (!isFiniteNumber(value)) return MISSING_VALUE_LABEL;
36767
36855
  if (formatPrice) return formatPrice(value);
36768
36856
  return `${Math.round(value * 100)}\xA2`;
36769
36857
  };
36770
36858
  var formatSignedPercent = (value) => {
36771
- if (!isFiniteNumber(value)) return missingLabel;
36859
+ if (!isFiniteNumber(value)) return MISSING_VALUE_LABEL;
36772
36860
  if (value === 0) return "0%";
36773
36861
  return `${value > 0 ? "+" : "-"}${percentFormatter.format(Math.abs(value))}%`;
36774
36862
  };
@@ -36856,10 +36944,6 @@ var getFinalPnlPercent = (position, pnlValue) => {
36856
36944
  }
36857
36945
  return null;
36858
36946
  };
36859
- var getPositionTone = (value) => {
36860
- if (!isFiniteNumber(value) || value === 0) return "neutral";
36861
- return value > 0 ? "positive" : "negative";
36862
- };
36863
36947
  var toPositionRowViewModel = (position, labels = defaultLabels2, formatters = {}) => {
36864
36948
  const { formatCurrency: currency, formatPrice: price } = formatters;
36865
36949
  const positionStatus = resolvePositionStatus(position);
@@ -36873,10 +36957,10 @@ var toPositionRowViewModel = (position, labels = defaultLabels2, formatters = {}
36873
36957
  position,
36874
36958
  positionStatus,
36875
36959
  bucket: resolvePositionBucket(position),
36876
- title: position.title || missingLabel,
36960
+ title: position.title || MISSING_VALUE_LABEL,
36877
36961
  thumbnailSrc: position.thumbnailSrc,
36878
- selectedOutcomeLabel: position.outcomeLabel || missingLabel,
36879
- resolutionLabel: position.resolutionLabel || position.outcomeLabel || missingLabel,
36962
+ selectedOutcomeLabel: position.outcomeLabel || MISSING_VALUE_LABEL,
36963
+ resolutionLabel: position.resolutionLabel || position.outcomeLabel || MISSING_VALUE_LABEL,
36880
36964
  venueShareBreakdown: position.venueShareBreakdown,
36881
36965
  totalTraded: {
36882
36966
  primaryLabel: formatCurrency(getTotalTradedValue(position), currency),
@@ -37513,11 +37597,6 @@ var import_jsx_runtime199 = require("react/jsx-runtime");
37513
37597
  var shouldUseNativeLinkNavigation3 = (event) => {
37514
37598
  return event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button === 1;
37515
37599
  };
37516
- var toneTextClassName = (tone) => {
37517
- if (tone === "positive") return "text-agg-success";
37518
- if (tone === "negative") return "text-agg-error";
37519
- return "text-agg-muted-foreground";
37520
- };
37521
37600
  var OutcomePill = ({ label: label2 }) => /* @__PURE__ */ (0, import_jsx_runtime199.jsx)("span", { className: "agg-position-outcome max-w-[120px] inline-flex items-center justify-center rounded-full bg-agg-secondary-hover px-4 py-[6px]", children: /* @__PURE__ */ (0, import_jsx_runtime199.jsx)("span", { className: "whitespace-nowrap font-agg-sans text-agg-sm leading-agg-5 font-agg-normal text-agg-foreground truncate", children: label2 }) });
37522
37601
  var ResolutionPill = ({ label: label2 }) => /* @__PURE__ */ (0, import_jsx_runtime199.jsx)("span", { className: "agg-position-resolution-pill inline-flex w-full items-center justify-center overflow-hidden rounded-full bg-agg-secondary-hover px-4 py-[6px] md:w-auto", children: /* @__PURE__ */ (0, import_jsx_runtime199.jsx)("span", { className: "truncate whitespace-nowrap font-agg-sans text-agg-sm leading-agg-5 font-agg-normal text-agg-foreground", children: label2 }) });
37523
37602
  var VenueShares = ({
@@ -37616,7 +37695,7 @@ var PositionValueCell = ({
37616
37695
  {
37617
37696
  className: cn(
37618
37697
  "font-agg-sans text-agg-sm leading-agg-5 font-agg-normal",
37619
- toneTextClassName(value.tone)
37698
+ toneClassName(value.tone)
37620
37699
  ),
37621
37700
  children: value.deltaLabel
37622
37701
  }
@@ -37629,7 +37708,7 @@ var PositionValueCell = ({
37629
37708
  {
37630
37709
  className: cn(
37631
37710
  "font-agg-sans text-agg-xs leading-agg-4 font-agg-normal",
37632
- toneTextClassName(value.tone)
37711
+ toneClassName(value.tone)
37633
37712
  ),
37634
37713
  children: value.percentLabel
37635
37714
  }
@@ -38554,7 +38633,7 @@ init_icon();
38554
38633
  init_tooltip();
38555
38634
  init_utils();
38556
38635
 
38557
- // src/pages/user-profile/components/default-avatar.tsx
38636
+ // src/shared/default-avatar.tsx
38558
38637
  init_utils();
38559
38638
  var import_jsx_runtime202 = require("react/jsx-runtime");
38560
38639
  var DefaultAvatar = ({ className }) => {
@@ -39953,6 +40032,450 @@ var UserProfilePage = ({
39953
40032
  };
39954
40033
  UserProfilePage.displayName = "UserProfilePage";
39955
40034
 
40035
+ // src/pages/leaderboard/index.tsx
40036
+ var import_hooks102 = require("@agg-build/hooks");
40037
+ var import_react69 = require("react");
40038
+ init_button();
40039
+ init_error_boundary();
40040
+ init_icon();
40041
+ init_state_message();
40042
+ init_utils();
40043
+
40044
+ // src/pages/leaderboard/components/leaderboard-header-row.tsx
40045
+ var import_hooks99 = require("@agg-build/hooks");
40046
+ init_utils();
40047
+
40048
+ // src/pages/leaderboard/leaderboard.constants.ts
40049
+ var LEADERBOARD_DEFAULT_PERIOD = "30d";
40050
+ var LEADERBOARD_DEFAULT_METRIC = "realizedPnl";
40051
+ var LEADERBOARD_METRICS = ["realizedPnl", "volume"];
40052
+ var LEADERBOARD_TOP_RANKS = 3;
40053
+ var LEADERBOARD_GRID_CLASS = "grid grid-cols-[36px_minmax(0,1fr)] grid-rows-[auto_auto] gap-x-3 gap-y-2 sm:grid-cols-[48px_minmax(0,1fr)_88px_128px_128px] sm:grid-rows-1 sm:gap-x-3 sm:gap-y-0";
40054
+
40055
+ // src/pages/leaderboard/components/leaderboard-header-row.tsx
40056
+ var import_jsx_runtime205 = require("react/jsx-runtime");
40057
+ var SORT_CARET = /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("svg", { viewBox: "0 0 10 10", className: "size-2.5", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("path", { d: "M5 8 1 3h8z", fill: "currentColor" }) });
40058
+ function LeaderboardHeaderRow({
40059
+ metric,
40060
+ onMetricChange
40061
+ }) {
40062
+ const labels = (0, import_hooks99.useLabels)().leaderboard;
40063
+ const sortable = (key, text) => {
40064
+ const active = metric === key;
40065
+ return /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
40066
+ "span",
40067
+ {
40068
+ role: "columnheader",
40069
+ "aria-sort": active ? "descending" : void 0,
40070
+ className: "text-right",
40071
+ children: /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
40072
+ "button",
40073
+ {
40074
+ type: "button",
40075
+ onClick: () => onMetricChange(key),
40076
+ className: cn(
40077
+ "inline-flex cursor-pointer items-center justify-end gap-1 uppercase tracking-wide outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-agg-primary-hover",
40078
+ active ? "font-agg-bold text-agg-foreground" : "hover:text-agg-foreground"
40079
+ ),
40080
+ children: [
40081
+ text,
40082
+ active ? SORT_CARET : null
40083
+ ]
40084
+ }
40085
+ )
40086
+ }
40087
+ );
40088
+ };
40089
+ return /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
40090
+ "div",
40091
+ {
40092
+ role: "row",
40093
+ className: cn(
40094
+ LEADERBOARD_GRID_CLASS,
40095
+ "agg-leaderboard-header hidden h-10 items-center border-b border-agg-separator bg-agg-secondary-hover px-5 text-agg-xs leading-agg-4 uppercase tracking-wide text-agg-muted-foreground sm:grid"
40096
+ ),
40097
+ children: [
40098
+ /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("span", { role: "columnheader", children: labels.columns.rank }),
40099
+ /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("span", { role: "columnheader", children: labels.columns.trader }),
40100
+ /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("span", { role: "columnheader", className: "text-right", children: labels.columns.orders }),
40101
+ sortable("volume", labels.columns.volume),
40102
+ sortable("realizedPnl", labels.columns.realizedPnl)
40103
+ ]
40104
+ }
40105
+ );
40106
+ }
40107
+
40108
+ // src/pages/leaderboard/components/leaderboard-row.tsx
40109
+ var import_hooks100 = require("@agg-build/hooks");
40110
+ init_remote_image();
40111
+ init_utils();
40112
+ var import_jsx_runtime206 = require("react/jsx-runtime");
40113
+ var integer = new Intl.NumberFormat("en-US");
40114
+ function LeaderboardRowView({
40115
+ row,
40116
+ isCurrentUser,
40117
+ className
40118
+ }) {
40119
+ var _a, _b, _c;
40120
+ const labels = (0, import_hooks100.useLabels)().leaderboard;
40121
+ const { formatCurrency: formatCurrency2 } = (0, import_hooks100.useAggUiConfig)().formatting;
40122
+ const tone = getPositionTone(row.realizedPnl);
40123
+ const shortWallet = shortenAddress(row.walletAddress);
40124
+ const identity = (_b = (_a = row.username) != null ? _a : shortWallet) != null ? _b : labels.anonymousTrader;
40125
+ const identityKind = row.username ? "username" : shortWallet ? "wallet" : "anonymous";
40126
+ const isTop = row.rank != null && row.rank <= LEADERBOARD_TOP_RANKS;
40127
+ const hasOrders = Number.isFinite(row.orders);
40128
+ const cell = (caption2, value, extra) => /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("span", { role: "cell", className: "flex flex-col text-left tabular-nums sm:block sm:text-right", children: [
40129
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("span", { className: "agg-type-caption uppercase tracking-wide text-agg-muted-foreground sm:hidden", children: caption2 }),
40130
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("span", { className: cn("text-agg-sm leading-agg-5", extra), children: value })
40131
+ ] });
40132
+ return /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(
40133
+ "div",
40134
+ {
40135
+ role: "row",
40136
+ "aria-current": isCurrentUser ? "true" : void 0,
40137
+ className: cn(
40138
+ LEADERBOARD_GRID_CLASS,
40139
+ "agg-leaderboard-row items-center px-4 py-3 sm:min-h-16 sm:px-5",
40140
+ isCurrentUser ? "bg-agg-trade-highlight-surface shadow-[inset_3px_0_0_var(--agg-color-primary)]" : "hover:bg-agg-secondary-hover/60",
40141
+ className
40142
+ ),
40143
+ children: [
40144
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
40145
+ "span",
40146
+ {
40147
+ role: "cell",
40148
+ "data-testid": "agg-leaderboard-rank",
40149
+ className: cn(
40150
+ "agg-leaderboard-rank row-span-2 inline-flex size-7 items-center justify-center rounded-agg-full text-agg-sm tabular-nums sm:row-span-1",
40151
+ // cn() is a plain join: colour classes must be mutually exclusive.
40152
+ row.rank === 1 ? "border border-agg-primary bg-agg-secondary-hover font-agg-bold text-agg-primary" : isTop ? "border border-agg-separator bg-agg-secondary-hover font-agg-bold text-agg-foreground" : "text-agg-muted-foreground"
40153
+ ),
40154
+ children: (_c = row.rank) != null ? _c : "\u2013"
40155
+ }
40156
+ ),
40157
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("div", { role: "cell", className: "agg-leaderboard-identity flex min-w-0 items-center gap-3", children: [
40158
+ row.avatarUrl ? /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
40159
+ RemoteImage,
40160
+ {
40161
+ src: (0, import_hooks100.optimizedImageUrl)(row.avatarUrl, 80),
40162
+ alt: "",
40163
+ className: "size-10 shrink-0 rounded-agg-full object-cover"
40164
+ }
40165
+ ) : /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(DefaultAvatar, { className: "size-10 rounded-agg-full" }),
40166
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("div", { className: "flex min-w-0 flex-col", children: [
40167
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("span", { className: "flex items-center gap-2", children: [
40168
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
40169
+ "span",
40170
+ {
40171
+ className: cn(
40172
+ "truncate text-agg-sm leading-agg-5",
40173
+ identityKind === "username" && "font-agg-bold text-agg-foreground",
40174
+ identityKind === "wallet" && "font-mono font-agg-medium text-agg-foreground",
40175
+ identityKind === "anonymous" && "font-agg-medium text-agg-muted-foreground"
40176
+ ),
40177
+ children: identity
40178
+ }
40179
+ ),
40180
+ isCurrentUser ? /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("span", { className: "rounded-agg-full bg-agg-primary px-1.5 text-agg-2xs font-agg-bold uppercase leading-agg-4 tracking-wide text-agg-on-primary", children: labels.you }) : null
40181
+ ] }),
40182
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("span", { className: "text-agg-xs leading-agg-4 text-agg-muted-foreground", children: hasOrders ? labels.tradesCount(row.orders) : MISSING_VALUE_LABEL })
40183
+ ] })
40184
+ ] }),
40185
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("div", { className: "col-start-2 grid grid-cols-3 gap-2 sm:contents", children: [
40186
+ cell(labels.columns.orders, hasOrders ? integer.format(row.orders) : MISSING_VALUE_LABEL),
40187
+ cell(labels.columns.volume, formatCurrencyMarkingNegligible(row.volume, formatCurrency2)),
40188
+ cell(
40189
+ labels.columns.realizedPnl,
40190
+ formatSignedCurrency(row.realizedPnl, formatCurrency2, { markNegligible: true }),
40191
+ cn("font-agg-bold", toneClassName(tone))
40192
+ )
40193
+ ] })
40194
+ ]
40195
+ }
40196
+ );
40197
+ }
40198
+
40199
+ // src/pages/leaderboard/components/leaderboard-skeleton.tsx
40200
+ var import_hooks101 = require("@agg-build/hooks");
40201
+ init_utils();
40202
+ var import_jsx_runtime207 = require("react/jsx-runtime");
40203
+ function LeaderboardSkeleton({ rows = 4 }) {
40204
+ const labels = (0, import_hooks101.useLabels)().leaderboard;
40205
+ return /* @__PURE__ */ (0, import_jsx_runtime207.jsx)("div", { role: "status", "aria-label": labels.loadingAria, className: "agg-leaderboard-skeleton", children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime207.jsxs)(
40206
+ "div",
40207
+ {
40208
+ className: cn(
40209
+ LEADERBOARD_GRID_CLASS,
40210
+ "items-center border-b border-agg-separator px-4 py-3 last:border-b-0 sm:min-h-16 sm:px-5"
40211
+ ),
40212
+ children: [
40213
+ /* @__PURE__ */ (0, import_jsx_runtime207.jsx)("span", { className: "size-7 rounded-agg-full bg-agg-secondary-hover/80" }),
40214
+ /* @__PURE__ */ (0, import_jsx_runtime207.jsxs)("div", { className: "flex items-center gap-3", children: [
40215
+ /* @__PURE__ */ (0, import_jsx_runtime207.jsx)("span", { className: "size-10 rounded-agg-full bg-agg-secondary-hover/80" }),
40216
+ /* @__PURE__ */ (0, import_jsx_runtime207.jsxs)("div", { className: "flex flex-1 flex-col gap-2", children: [
40217
+ /* @__PURE__ */ (0, import_jsx_runtime207.jsx)("span", { className: "h-3 w-2/5 rounded-agg-sm bg-agg-secondary-hover/80" }),
40218
+ /* @__PURE__ */ (0, import_jsx_runtime207.jsx)("span", { className: "h-3 w-1/5 rounded-agg-sm bg-agg-secondary-hover/80" })
40219
+ ] })
40220
+ ] }),
40221
+ /* @__PURE__ */ (0, import_jsx_runtime207.jsx)("span", { className: "hidden h-3 w-10 justify-self-end rounded-agg-sm bg-agg-secondary-hover/80 sm:block" }),
40222
+ /* @__PURE__ */ (0, import_jsx_runtime207.jsx)("span", { className: "hidden h-3 w-16 justify-self-end rounded-agg-sm bg-agg-secondary-hover/80 sm:block" }),
40223
+ /* @__PURE__ */ (0, import_jsx_runtime207.jsx)("span", { className: "hidden h-3 w-14 justify-self-end rounded-agg-sm bg-agg-secondary-hover/80 sm:block" })
40224
+ ]
40225
+ },
40226
+ i
40227
+ )) });
40228
+ }
40229
+
40230
+ // src/pages/leaderboard/components/segmented-control.tsx
40231
+ init_utils();
40232
+ var import_jsx_runtime208 = require("react/jsx-runtime");
40233
+ function SegmentedControl({
40234
+ label: label2,
40235
+ value,
40236
+ onChange,
40237
+ items,
40238
+ className,
40239
+ itemClassName
40240
+ }) {
40241
+ return /* @__PURE__ */ (0, import_jsx_runtime208.jsx)(
40242
+ "div",
40243
+ {
40244
+ role: "group",
40245
+ "aria-label": label2,
40246
+ className: cn(
40247
+ "agg-segmented flex h-10 w-full items-stretch overflow-clip rounded-agg-sm border border-agg-separator sm:w-auto",
40248
+ className
40249
+ ),
40250
+ children: items.map((item, idx) => {
40251
+ const isActive = item.value === value;
40252
+ return /* @__PURE__ */ (0, import_jsx_runtime208.jsxs)("div", { className: "flex flex-1 items-stretch sm:flex-none", children: [
40253
+ idx > 0 ? /* @__PURE__ */ (0, import_jsx_runtime208.jsx)("div", { className: "w-px bg-agg-separator", "aria-hidden": true }) : null,
40254
+ /* @__PURE__ */ (0, import_jsx_runtime208.jsx)(
40255
+ "button",
40256
+ {
40257
+ type: "button",
40258
+ "aria-pressed": isActive,
40259
+ onClick: () => onChange(item.value),
40260
+ className: cn(
40261
+ "agg-segmented-trigger flex flex-1 cursor-pointer items-center justify-center px-3 font-agg-sans text-agg-sm leading-agg-5 whitespace-nowrap outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-agg-primary-hover sm:px-4",
40262
+ isActive ? "bg-agg-secondary-hover font-agg-bold text-agg-foreground" : "bg-agg-secondary font-agg-normal text-agg-muted-foreground hover:bg-agg-secondary-hover hover:text-agg-foreground",
40263
+ itemClassName
40264
+ ),
40265
+ children: item.label
40266
+ }
40267
+ )
40268
+ ] }, item.value);
40269
+ })
40270
+ }
40271
+ );
40272
+ }
40273
+
40274
+ // src/pages/leaderboard/index.tsx
40275
+ var import_jsx_runtime209 = require("react/jsx-runtime");
40276
+ function LeaderboardPage(props) {
40277
+ return /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(AggErrorBoundary, { onError: props.onError, children: /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(LeaderboardPageInner, __spreadValues({}, props)) });
40278
+ }
40279
+ function LeaderboardPageInner({
40280
+ rows: rowsProp,
40281
+ isLoading: isLoadingProp,
40282
+ error: errorProp,
40283
+ hasNextPage: hasNextPageProp,
40284
+ isLoadingMore: isLoadingMoreProp,
40285
+ onLoadMore: onLoadMoreProp,
40286
+ period: periodProp,
40287
+ onPeriodChange,
40288
+ metric: metricProp,
40289
+ onMetricChange,
40290
+ currentUserId: currentUserIdProp,
40291
+ appName,
40292
+ className,
40293
+ classNames
40294
+ }) {
40295
+ const allLabels = (0, import_hooks102.useLabels)();
40296
+ const labels = allLabels.leaderboard;
40297
+ const { user } = (0, import_hooks102.useAggAuthState)();
40298
+ const [periodState, setPeriodState] = (0, import_react69.useState)(LEADERBOARD_DEFAULT_PERIOD);
40299
+ const [metricState, setMetricState] = (0, import_react69.useState)(LEADERBOARD_DEFAULT_METRIC);
40300
+ const period = periodProp != null ? periodProp : periodState;
40301
+ const metric = metricProp != null ? metricProp : metricState;
40302
+ const handlePeriodChange = (0, import_react69.useCallback)(
40303
+ (next) => {
40304
+ if (periodProp === void 0) setPeriodState(next);
40305
+ onPeriodChange == null ? void 0 : onPeriodChange(next);
40306
+ },
40307
+ [onPeriodChange, periodProp]
40308
+ );
40309
+ const handleMetricChange = (0, import_react69.useCallback)(
40310
+ (next) => {
40311
+ if (metricProp === void 0) setMetricState(next);
40312
+ onMetricChange == null ? void 0 : onMetricChange(next);
40313
+ },
40314
+ [metricProp, onMetricChange]
40315
+ );
40316
+ const shouldUseHookData = !rowsProp;
40317
+ const query = (0, import_hooks102.useLeaderboard)({ period, metric, enabled: shouldUseHookData });
40318
+ const rows = rowsProp != null ? rowsProp : query.rows;
40319
+ const isLoading = isLoadingProp != null ? isLoadingProp : shouldUseHookData && query.isLoading;
40320
+ const error = errorProp != null ? errorProp : shouldUseHookData ? query.error : null;
40321
+ const hasNextPage = hasNextPageProp != null ? hasNextPageProp : shouldUseHookData && query.hasNextPage;
40322
+ const isLoadingMore = isLoadingMoreProp != null ? isLoadingMoreProp : shouldUseHookData && query.isFetchingNextPage;
40323
+ const fetchNextPage = query.fetchNextPage;
40324
+ const onLoadMore = (0, import_react69.useMemo)(
40325
+ () => onLoadMoreProp != null ? onLoadMoreProp : shouldUseHookData ? () => void fetchNextPage() : void 0,
40326
+ [onLoadMoreProp, shouldUseHookData, fetchNextPage]
40327
+ );
40328
+ const retry = shouldUseHookData ? () => void query.refetch() : void 0;
40329
+ const currentUserId = currentUserIdProp != null ? currentUserIdProp : user == null ? void 0 : user.id;
40330
+ const [sentinel, setSentinel] = (0, import_react69.useState)(null);
40331
+ (0, import_react69.useEffect)(() => {
40332
+ const target = sentinel;
40333
+ if (!target || !hasNextPage || !onLoadMore || typeof IntersectionObserver === "undefined")
40334
+ return;
40335
+ const observer = new IntersectionObserver(
40336
+ (entries) => {
40337
+ var _a;
40338
+ if (!((_a = entries[0]) == null ? void 0 : _a.isIntersecting) || isLoading || isLoadingMore) return;
40339
+ onLoadMore();
40340
+ },
40341
+ { rootMargin: "60px 0px" }
40342
+ );
40343
+ observer.observe(target);
40344
+ return () => observer.disconnect();
40345
+ }, [sentinel, hasNextPage, isLoading, isLoadingMore, onLoadMore]);
40346
+ const hasRows = rows.length > 0;
40347
+ const showInlineError = Boolean(error) && hasRows;
40348
+ const periodItems = import_hooks102.LEADERBOARD_PERIODS.map((value) => ({ value, label: labels.periods[value] }));
40349
+ const metricItems = LEADERBOARD_METRICS.map((value) => ({ value, label: labels.metrics[value] }));
40350
+ return /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)(
40351
+ "div",
40352
+ {
40353
+ className: cn(
40354
+ "agg-leaderboard mx-auto flex w-full max-w-[960px] flex-col px-4 py-6 sm:px-6 gap-5 font-agg-sans text-agg-foreground",
40355
+ className,
40356
+ classNames == null ? void 0 : classNames.root
40357
+ ),
40358
+ children: [
40359
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)("header", { className: cn("agg-leaderboard-title flex flex-col gap-1", classNames == null ? void 0 : classNames.header), children: [
40360
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("h1", { className: "agg-type-heading m-0", children: labels.title }),
40361
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("p", { className: "m-0 text-agg-sm leading-agg-5 text-agg-muted-foreground", children: labels.subtitle(appName, labels.periods[period]) })
40362
+ ] }),
40363
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)(
40364
+ "div",
40365
+ {
40366
+ className: cn(
40367
+ "agg-leaderboard-toolbar flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between",
40368
+ classNames == null ? void 0 : classNames.toolbar
40369
+ ),
40370
+ children: [
40371
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3", children: [
40372
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("span", { className: "agg-type-caption uppercase tracking-wide text-agg-muted-foreground", children: labels.periodLabel }),
40373
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
40374
+ SegmentedControl,
40375
+ {
40376
+ label: labels.periodLabel,
40377
+ value: period,
40378
+ onChange: handlePeriodChange,
40379
+ items: periodItems
40380
+ }
40381
+ )
40382
+ ] }),
40383
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3", children: [
40384
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("span", { className: "agg-type-caption uppercase tracking-wide text-agg-muted-foreground", children: labels.rankByLabel }),
40385
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
40386
+ SegmentedControl,
40387
+ {
40388
+ label: labels.rankByLabel,
40389
+ value: metric,
40390
+ onChange: handleMetricChange,
40391
+ items: metricItems
40392
+ }
40393
+ )
40394
+ ] })
40395
+ ]
40396
+ }
40397
+ ),
40398
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)(
40399
+ "section",
40400
+ {
40401
+ "aria-label": labels.title,
40402
+ className: cn(
40403
+ "agg-leaderboard-list overflow-clip rounded-agg-xl border border-agg-separator bg-agg-secondary shadow-agg-card",
40404
+ classNames == null ? void 0 : classNames.list
40405
+ ),
40406
+ children: [
40407
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)("div", { role: "table", "aria-label": labels.title, className: "agg-leaderboard-table", children: [
40408
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(LeaderboardHeaderRow, { metric, onMetricChange: handleMetricChange }),
40409
+ !isLoading && hasRows ? /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("div", { className: "divide-y divide-agg-separator", children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
40410
+ LeaderboardRowView,
40411
+ {
40412
+ row,
40413
+ isCurrentUser: currentUserId !== void 0 && row.userId === currentUserId,
40414
+ className: classNames == null ? void 0 : classNames.row
40415
+ },
40416
+ row.userId
40417
+ )) }) : null
40418
+ ] }),
40419
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(LeaderboardSkeleton, {}) : error && !hasRows ? /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("div", { className: "py-10", children: /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
40420
+ StateMessage,
40421
+ {
40422
+ title: labels.errorTitle,
40423
+ description: labels.errorDescription,
40424
+ icon: /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(Icon, { name: "warning" }),
40425
+ onAction: retry
40426
+ }
40427
+ ) }) : rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("div", { className: "py-10", children: /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
40428
+ StateMessage,
40429
+ {
40430
+ title: labels.emptyTitle,
40431
+ description: labels.emptyDescription,
40432
+ icon: /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(Icon, { name: "search-empty" })
40433
+ }
40434
+ ) }) : null,
40435
+ (hasNextPage || showInlineError) && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
40436
+ "div",
40437
+ {
40438
+ className: cn(
40439
+ "agg-leaderboard-footer relative flex items-center justify-center gap-3 border-t border-agg-separator p-3.5",
40440
+ classNames == null ? void 0 : classNames.footer
40441
+ ),
40442
+ children: showInlineError ? /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)(import_jsx_runtime209.Fragment, { children: [
40443
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("span", { role: "alert", className: "text-agg-sm leading-agg-5 text-agg-error", children: labels.errorTitle }),
40444
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(Button, { variant: "tertiary", size: "small", onClick: retry != null ? retry : onLoadMore, children: allLabels.common.retry })
40445
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)(import_jsx_runtime209.Fragment, { children: [
40446
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
40447
+ "div",
40448
+ {
40449
+ ref: setSentinel,
40450
+ className: "agg-leaderboard-sentinel absolute inset-x-0 top-0 h-px",
40451
+ "aria-hidden": true
40452
+ }
40453
+ ),
40454
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
40455
+ Button,
40456
+ {
40457
+ variant: "tertiary",
40458
+ size: "small",
40459
+ onClick: onLoadMore,
40460
+ disabled: isLoadingMore,
40461
+ isLoading: isLoadingMore,
40462
+ "aria-label": labels.showMore,
40463
+ children: labels.showMore
40464
+ }
40465
+ )
40466
+ ] })
40467
+ }
40468
+ ) : null
40469
+ ]
40470
+ }
40471
+ ),
40472
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("p", { className: "m-0 text-agg-xs leading-agg-4 text-agg-muted-foreground", children: labels.pnlFootnote })
40473
+ ]
40474
+ }
40475
+ );
40476
+ }
40477
+ LeaderboardPage.displayName = "LeaderboardPage";
40478
+
39956
40479
  // src/pages/index.ts
39957
40480
  init_deposit_modal_events();
39958
40481
  // Annotate the CommonJS export names for ESM import in node:
@@ -39962,6 +40485,10 @@ init_deposit_modal_events();
39962
40485
  EventOpenOrders,
39963
40486
  EventOpenOrdersCard,
39964
40487
  HomePage,
40488
+ LEADERBOARD_DEFAULT_METRIC,
40489
+ LEADERBOARD_DEFAULT_PERIOD,
40490
+ LEADERBOARD_METRICS,
40491
+ LeaderboardPage,
39965
40492
  ManageBalancesModal,
39966
40493
  USER_PROFILE_TAB_ACTIVITY,
39967
40494
  USER_PROFILE_TAB_OPEN_ORDERS,