@agg-build/ui 4.4.0 → 4.7.2

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 (31) hide show
  1. package/README.md +4 -0
  2. package/dist/{chunk-WW5QKNIM.mjs → chunk-3UBMK2YH.mjs} +302 -26
  3. package/dist/{chunk-V5CRUO6S.mjs → chunk-C4GFVJ62.mjs} +98 -30
  4. package/dist/{chunk-64BBTXFE.mjs → chunk-KDBKKJ7W.mjs} +68 -35
  5. package/dist/{chunk-UCU2XCV5.mjs → chunk-LXQ3U4X2.mjs} +2 -2
  6. package/dist/{chunk-N7UPPT5J.mjs → chunk-RDBMHBR2.mjs} +14 -0
  7. package/dist/{chunk-6STRIKUA.mjs → chunk-WYCSTAN7.mjs} +1 -1
  8. package/dist/{chunk-734VTGCV.mjs → chunk-XN2NB2NP.mjs} +1 -1
  9. package/dist/events.js +97 -25
  10. package/dist/events.mjs +3 -3
  11. package/dist/index.js +464 -79
  12. package/dist/index.mjs +7 -7
  13. package/dist/modals.mjs +3 -3
  14. package/dist/pages.js +464 -79
  15. package/dist/pages.mjs +6 -6
  16. package/dist/primitives.mjs +1 -1
  17. package/dist/trading.js +65 -32
  18. package/dist/trading.mjs +4 -4
  19. package/dist/types/events/list/event-list.constants.d.mts +3 -1
  20. package/dist/types/events/list/event-list.constants.d.ts +3 -1
  21. package/dist/types/events/list/event-list.types.d.mts +17 -0
  22. package/dist/types/events/list/event-list.types.d.ts +17 -0
  23. package/dist/types/events/list/event-list.utils.d.mts +4 -0
  24. package/dist/types/events/list/event-list.utils.d.ts +4 -0
  25. package/dist/types/events/list/index.d.mts +2 -2
  26. package/dist/types/events/list/index.d.ts +2 -2
  27. package/dist/types/pages/home/event-discovery-url-state.d.mts +35 -0
  28. package/dist/types/pages/home/event-discovery-url-state.d.ts +35 -0
  29. package/dist/types/trading/place-order/index.place-order.utils.d.mts +26 -0
  30. package/dist/types/trading/place-order/index.place-order.utils.d.ts +26 -0
  31. package/package.json +3 -3
package/dist/pages.js CHANGED
@@ -4874,6 +4874,19 @@ var resolveCategoryIdsFromPath = (path, fallbackCategoryIds) => {
4874
4874
  if (deepest) return [deepest];
4875
4875
  return fallbackCategoryIds;
4876
4876
  };
4877
+ var validateSubcategoryPath = (requestedPath, rootCategoryId, childrenByParentId) => {
4878
+ var _a;
4879
+ if (!rootCategoryId) return [];
4880
+ const validPath = [];
4881
+ let parentId = rootCategoryId;
4882
+ for (const categoryId of requestedPath) {
4883
+ const category = (_a = childrenByParentId.get(parentId)) == null ? void 0 : _a.find((child) => child.id === categoryId);
4884
+ if (!category) break;
4885
+ validPath.push(category.id);
4886
+ parentId = category.id;
4887
+ }
4888
+ return validPath;
4889
+ };
4877
4890
  var resolveTabVenus = (tab, visibleVenues) => {
4878
4891
  const applyAllowList = (venues) => {
4879
4892
  if (!venues) {
@@ -10301,6 +10314,13 @@ var import_react16 = require("react");
10301
10314
  // src/events/list/event-list.constants.ts
10302
10315
  var import_sdk13 = require("@agg-build/sdk");
10303
10316
  var DEFAULT_EVENTS_LIMIT = 50;
10317
+ var DEFAULT_EVENT_LIST_SORT = "volume24hr";
10318
+ var EVENT_LIST_SORT_VALUES = [
10319
+ "volume24hr",
10320
+ "topArbitrage",
10321
+ "volume",
10322
+ "endDate"
10323
+ ];
10304
10324
  var getDefaultEventListTabs = (labels) => {
10305
10325
  return [
10306
10326
  {
@@ -10370,6 +10390,7 @@ var getDefaultEventListTabs = (labels) => {
10370
10390
 
10371
10391
  // src/events/list/event-list-tabs.tsx
10372
10392
  var import_jsx_runtime134 = require("react/jsx-runtime");
10393
+ var DEFAULT_HIDDEN_VENUES = new Set((0, import_sdk14.getEffectiveDisabledVenues)(void 0));
10373
10394
  var renderTabIcon = (tab, isActive) => {
10374
10395
  if (tab.iconName === "warning-filled") {
10375
10396
  return /* @__PURE__ */ (0, import_jsx_runtime134.jsx)(Icon, { name: "warning-filled", size: "small", color: "currentColor" });
@@ -10398,15 +10419,11 @@ var useEventListTabs = (tabs) => {
10398
10419
  const availabilityState = (0, import_hooks37.getVenueAvailabilityState)({
10399
10420
  venueId: tab.venueLogo,
10400
10421
  disabledVenues,
10401
- // A compile-time-inactive venue (novig today) is hidden by default and
10402
- // un-hidden per-environment by NOVIG_DATA_VISIBLE, so its
10403
- // disabled-ness is only known once `/app/config` resolves — treating
10404
- // it as hidden while that request is in flight stops its tab flashing
10405
- // in and out where the flag is unset. Active venues must NOT be
10406
- // withheld, or they pop in late. Keyed off the shared inactive-venue
10407
- // helper rather than a venue name, so launching or retiring one needs
10408
- // no change here.
10409
- isConfigLoading: isAppConfigLoading && (0, import_sdk14.isVenueInactive)(tab.venueLogo),
10422
+ // A globally inactive or default-disabled venue is hidden until
10423
+ // `/app/config` resolves. That prevents partner-opt-in venues such as
10424
+ // Novig from flashing briefly for apps that still disable them, while
10425
+ // ordinary active venues continue rendering immediately.
10426
+ isConfigLoading: isAppConfigLoading && ((0, import_sdk14.isVenueInactive)(tab.venueLogo) || DEFAULT_HIDDEN_VENUES.has(tab.venueLogo)),
10410
10427
  isLocationBlocked
10411
10428
  });
10412
10429
  if (availabilityState === "hidden") return [];
@@ -10584,10 +10601,16 @@ var EventList = ({
10584
10601
  getMarketHref,
10585
10602
  getEventHref,
10586
10603
  initialVenueTab,
10604
+ activeVenueTab: controlledActiveVenueTab,
10605
+ onActiveVenueTabChange,
10606
+ selectedSort: controlledSelectedSort,
10607
+ onSelectedSortChange,
10608
+ categoryPath: controlledCategoryPath,
10609
+ onCategoryPathChange,
10587
10610
  initialLoadedPageCount,
10588
10611
  stateRef
10589
10612
  }) => {
10590
- var _a, _b, _c, _d, _e;
10613
+ var _a, _b, _c, _d, _e, _f;
10591
10614
  const labels = (0, import_hooks38.useLabels)();
10592
10615
  const { disabledVenues } = (0, import_hooks38.useAppConfig)();
10593
10616
  const {
@@ -10599,13 +10622,37 @@ var EventList = ({
10599
10622
  () => disabledVenues.length === 0 ? void 0 : (0, import_hooks38.getVisibleVenueIdsByConfig)(import_sdk15.VENUES, disabledVenues),
10600
10623
  [disabledVenues]
10601
10624
  );
10602
- const [activeTabValue, setActiveTabValue] = (0, import_react17.useState)(
10625
+ const [internalActiveTabValue, setInternalActiveTabValue] = (0, import_react17.useState)(
10603
10626
  (_b = initialVenueTab != null ? initialVenueTab : (_a = resolvedTabs[0]) == null ? void 0 : _a.value) != null ? _b : "matched"
10604
10627
  );
10605
- const [selectedSort, setSelectedSort] = (0, import_react17.useState)("volume24hr");
10628
+ const activeTabValue = controlledActiveVenueTab != null ? controlledActiveVenueTab : internalActiveTabValue;
10629
+ const [internalSelectedSort, setInternalSelectedSort] = (0, import_react17.useState)(DEFAULT_EVENT_LIST_SORT);
10630
+ const selectedSort = controlledSelectedSort != null ? controlledSelectedSort : internalSelectedSort;
10606
10631
  const [isSubcategoriesModalOpen, setIsSubcategoriesModalOpen] = (0, import_react17.useState)(false);
10607
- const [categoryPath, setCategoryPath] = (0, import_react17.useState)([]);
10632
+ const [internalCategoryPath, setInternalCategoryPath] = (0, import_react17.useState)([]);
10633
+ const categoryPath = controlledCategoryPath != null ? controlledCategoryPath : internalCategoryPath;
10608
10634
  const [collapsedCategoryIds, setCollapsedCategoryIds] = (0, import_react17.useState)(() => /* @__PURE__ */ new Set());
10635
+ const handleActiveTabChange = (0, import_react17.useCallback)(
10636
+ (value) => {
10637
+ if (controlledActiveVenueTab == null) setInternalActiveTabValue(value);
10638
+ onActiveVenueTabChange == null ? void 0 : onActiveVenueTabChange(value, { history: "push" });
10639
+ },
10640
+ [controlledActiveVenueTab, onActiveVenueTabChange]
10641
+ );
10642
+ const handleSelectedSortChange = (0, import_react17.useCallback)(
10643
+ (value) => {
10644
+ if (controlledSelectedSort == null) setInternalSelectedSort(value);
10645
+ onSelectedSortChange == null ? void 0 : onSelectedSortChange(value, { history: "push" });
10646
+ },
10647
+ [controlledSelectedSort, onSelectedSortChange]
10648
+ );
10649
+ const handleCategoryPathChange = (0, import_react17.useCallback)(
10650
+ (value, options) => {
10651
+ if (controlledCategoryPath == null) setInternalCategoryPath(value);
10652
+ onCategoryPathChange == null ? void 0 : onCategoryPathChange(value, options);
10653
+ },
10654
+ [controlledCategoryPath, onCategoryPathChange]
10655
+ );
10609
10656
  const sortItems = (0, import_react17.useMemo)(() => {
10610
10657
  return [
10611
10658
  {
@@ -10638,9 +10685,9 @@ var EventList = ({
10638
10685
  const baseCategoryId = (_c = categoryIds == null ? void 0 : categoryIds[0]) != null ? _c : null;
10639
10686
  (0, import_react17.useEffect)(() => {
10640
10687
  if (!isDiscoveryFiltersEnabled) return;
10641
- setCategoryPath([]);
10688
+ if (controlledCategoryPath == null) setInternalCategoryPath([]);
10642
10689
  setCollapsedCategoryIds(/* @__PURE__ */ new Set());
10643
- }, [baseCategoryId, isDiscoveryFiltersEnabled]);
10690
+ }, [baseCategoryId, controlledCategoryPath, isDiscoveryFiltersEnabled]);
10644
10691
  const { categories: topLevelCategories } = (0, import_hooks38.useCategories)({
10645
10692
  queryKeyScope: "event-list-top-categories",
10646
10693
  enabled: isDiscoveryFiltersEnabled,
@@ -10652,12 +10699,13 @@ var EventList = ({
10652
10699
  const baseCategoryChildPrefetchIds = (0, import_react17.useMemo)(() => {
10653
10700
  return Array.from(
10654
10701
  /* @__PURE__ */ new Set([
10702
+ ...baseCategoryId ? [baseCategoryId] : [],
10655
10703
  ...sortedTopLevelCategories.map((category) => category.id),
10656
10704
  ...categoryPath.map((category) => category.id)
10657
10705
  ])
10658
10706
  );
10659
- }, [categoryPath, sortedTopLevelCategories]);
10660
- const { childrenByParentId: baseChildrenByParentId } = (0, import_hooks38.useCategoryChildren)({
10707
+ }, [baseCategoryId, categoryPath, sortedTopLevelCategories]);
10708
+ const { childrenByParentId: baseChildrenByParentId, isLoading: isBaseCategoryChildrenLoading } = (0, import_hooks38.useCategoryChildren)({
10661
10709
  queryKeyScope: "event-list-category-children",
10662
10710
  enabled: isDiscoveryFiltersEnabled,
10663
10711
  parentIds: baseCategoryChildPrefetchIds,
@@ -10707,7 +10755,36 @@ var EventList = ({
10707
10755
  ...visibleGrandchildrenByParentId
10708
10756
  ]);
10709
10757
  }, [baseChildrenByParentId, visibleChildrenByParentId, visibleGrandchildrenByParentId]);
10710
- const shouldRenderSubcategoryFilters = isDiscoveryFiltersEnabled && baseCategoryId !== null && (((_e = (_d = childrenByParentId.get(baseCategoryId)) == null ? void 0 : _d.length) != null ? _e : 0) > 0 || categoryPath.length > 0);
10758
+ const controlledCategoryPathKey = (_d = controlledCategoryPath == null ? void 0 : controlledCategoryPath.map((entry) => entry.id).join(",")) != null ? _d : "";
10759
+ const controlledCategoryPathValidationKey = `${baseCategoryId != null ? baseCategoryId : ""}|${controlledCategoryPathKey}`;
10760
+ const [validatedCategoryPathKey, setValidatedCategoryPathKey] = (0, import_react17.useState)(
10761
+ () => controlledCategoryPath == null || controlledCategoryPath.length === 0 ? controlledCategoryPathValidationKey : ""
10762
+ );
10763
+ (0, import_react17.useEffect)(() => {
10764
+ if (controlledCategoryPath == null || controlledCategoryPath.length === 0) {
10765
+ setValidatedCategoryPathKey(controlledCategoryPathValidationKey);
10766
+ return;
10767
+ }
10768
+ if (isBaseCategoryChildrenLoading) return;
10769
+ const requestedIds = controlledCategoryPath.map((entry) => entry.id);
10770
+ const validIds = validateSubcategoryPath(requestedIds, baseCategoryId, baseChildrenByParentId);
10771
+ if (validIds.length !== requestedIds.length) {
10772
+ handleCategoryPathChange(controlledCategoryPath.slice(0, validIds.length), {
10773
+ history: "replace"
10774
+ });
10775
+ return;
10776
+ }
10777
+ setValidatedCategoryPathKey(controlledCategoryPathValidationKey);
10778
+ }, [
10779
+ baseCategoryId,
10780
+ baseChildrenByParentId,
10781
+ controlledCategoryPath,
10782
+ controlledCategoryPathKey,
10783
+ controlledCategoryPathValidationKey,
10784
+ handleCategoryPathChange,
10785
+ isBaseCategoryChildrenLoading
10786
+ ]);
10787
+ const shouldRenderSubcategoryFilters = isDiscoveryFiltersEnabled && baseCategoryId !== null && (((_f = (_e = childrenByParentId.get(baseCategoryId)) == null ? void 0 : _e.length) != null ? _f : 0) > 0 || categoryPath.length > 0);
10711
10788
  const baseCategoryEventCount = (0, import_react17.useMemo)(() => {
10712
10789
  var _a2, _b2;
10713
10790
  return (_b2 = (_a2 = sortedTopLevelCategories.find((c) => c.id === baseCategoryId)) == null ? void 0 : _a2.eventCount) != null ? _b2 : 0;
@@ -10765,7 +10842,8 @@ var EventList = ({
10765
10842
  // markets experience is enabled (the sports event-detail view loads the
10766
10843
  // folded companions via aggKey). Gated on the same flag as that view.
10767
10844
  grouped: showSportsMarkets,
10768
- initialPages: initialLoadedPageCount
10845
+ initialPages: initialLoadedPageCount,
10846
+ enabled: controlledCategoryPath == null || validatedCategoryPathKey === controlledCategoryPathValidationKey
10769
10847
  });
10770
10848
  (0, import_react17.useEffect)(() => {
10771
10849
  if (stateRef) {
@@ -10826,7 +10904,7 @@ var EventList = ({
10826
10904
  "grid grid-cols-[repeat(auto-fill,minmax(240px,1fr))] md:grid-cols-[repeat(auto-fill,minmax(360px,1fr))] gap-4"
10827
10905
  );
10828
10906
  const handleSelectAllCategories = () => {
10829
- setCategoryPath([]);
10907
+ handleCategoryPathChange([], { history: "push" });
10830
10908
  setCollapsedCategoryIds(/* @__PURE__ */ new Set());
10831
10909
  onCategoryRootChange == null ? void 0 : onCategoryRootChange(baseCategoryId != null ? baseCategoryId : void 0);
10832
10910
  setIsSubcategoriesModalOpen(false);
@@ -10838,7 +10916,7 @@ var EventList = ({
10838
10916
  isExpanded,
10839
10917
  isSelected
10840
10918
  }) => {
10841
- setCategoryPath((prev) => [...prev.slice(0, depth), entry]);
10919
+ handleCategoryPathChange([...categoryPath.slice(0, depth), entry], { history: "push" });
10842
10920
  setCollapsedCategoryIds((prev) => {
10843
10921
  const next = new Set(prev);
10844
10922
  if (hasKnownChildren && isExpanded && isSelected) {
@@ -10878,7 +10956,7 @@ var EventList = ({
10878
10956
  ariaLabel: labels.eventList.tabsAria(title2),
10879
10957
  className: "agg-event-list-tabs min-w-0 flex-1 max-w-[600px]!",
10880
10958
  activeTab: activeTabValue,
10881
- onTabChange: setActiveTabValue,
10959
+ onTabChange: handleActiveTabChange,
10882
10960
  overflowBehavior: "scroll"
10883
10961
  }
10884
10962
  ),
@@ -10888,7 +10966,7 @@ var EventList = ({
10888
10966
  ariaLabel: labels.eventList.sortByLabel,
10889
10967
  className: "min-w-[200px] w-auto! shrink-0 min-h-10.5",
10890
10968
  value: selectedSort,
10891
- onChange: setSelectedSort,
10969
+ onChange: handleSelectedSortChange,
10892
10970
  items: sortItems,
10893
10971
  contentClassName: "py-2",
10894
10972
  triggerClassName: "rounded-agg-lg!"
@@ -10905,7 +10983,7 @@ var EventList = ({
10905
10983
  ariaLabel: labels.eventList.tabsAria(title2),
10906
10984
  className: "agg-event-list-tabs min-w-0 flex-1",
10907
10985
  activeTab: activeTabValue,
10908
- onTabChange: setActiveTabValue,
10986
+ onTabChange: handleActiveTabChange,
10909
10987
  overflowBehavior: "select"
10910
10988
  }
10911
10989
  ),
@@ -10915,7 +10993,7 @@ var EventList = ({
10915
10993
  ariaLabel: labels.eventList.sortByLabel,
10916
10994
  className: "min-w-0 flex-1 md:min-w-[144px]",
10917
10995
  value: selectedSort,
10918
- onChange: setSelectedSort,
10996
+ onChange: handleSelectedSortChange,
10919
10997
  items: sortItems,
10920
10998
  contentClassName: "rounded-[12px] py-2 shadow-[0_8px_16px_rgba(0,0,0,0.1)]"
10921
10999
  }
@@ -18441,6 +18519,37 @@ var findMatchingVenueOutcome = (market, selectedOutcome) => {
18441
18519
  return normalizedLabel !== "" && selectedNames.has(normalizedLabel);
18442
18520
  })) != null ? _b : null;
18443
18521
  };
18522
+ var resolveSellableSharesByVenue = ({
18523
+ positions,
18524
+ market,
18525
+ selectedOutcome
18526
+ }) => {
18527
+ var _a, _b, _c, _d, _e, _f, _g;
18528
+ const sharesByVenue = /* @__PURE__ */ new Map();
18529
+ if (!market || !selectedOutcome) return sharesByVenue;
18530
+ const normalizedSelectedOutcomeLabel = normalizeOutcomeName(selectedOutcome.label);
18531
+ const selectedMarketIdSet = new Set(
18532
+ [
18533
+ market.id,
18534
+ (_a = market.marketId) != null ? _a : void 0,
18535
+ (_b = market.externalIdentifier) != null ? _b : void 0,
18536
+ ...((_c = market.matchedVenueMarkets) != null ? _c : []).map((matched) => matched.id)
18537
+ ].filter((value) => Boolean(value))
18538
+ );
18539
+ for (const group of positions) {
18540
+ for (const outcome of (_e = (_d = group.venueMarket) == null ? void 0 : _d.venueMarketOutcomes) != null ? _e : []) {
18541
+ if (normalizeOutcomeName(outcome.label) !== normalizedSelectedOutcomeLabel) continue;
18542
+ for (const breakdown of (_f = outcome.venueBreakdown) != null ? _f : []) {
18543
+ const matchesMarketId = selectedMarketIdSet.size === 0 || selectedMarketIdSet.has(group.targetMarketId) || selectedMarketIdSet.has(breakdown.venueMarketId);
18544
+ if (!matchesMarketId) continue;
18545
+ const size = Number.isFinite(breakdown.size) ? breakdown.size : 0;
18546
+ if (size <= 0) continue;
18547
+ sharesByVenue.set(breakdown.venue, ((_g = sharesByVenue.get(breakdown.venue)) != null ? _g : 0) + size);
18548
+ }
18549
+ }
18550
+ }
18551
+ return sharesByVenue;
18552
+ };
18444
18553
  var buildLimitOrderVenueOptions = ({
18445
18554
  currentPrices,
18446
18555
  livePrices,
@@ -18525,7 +18634,7 @@ var getSmartRouteTotalFees = (feeBreakdown) => {
18525
18634
  if (!feeBreakdown) return null;
18526
18635
  const feeParts = [feeBreakdown.venueFees, feeBreakdown.bridgeFees, feeBreakdown.executionGas];
18527
18636
  if (!feeParts.every(Number.isFinite)) return null;
18528
- return feeParts.reduce((total, fee) => total + fee, 0);
18637
+ return feeParts.reduce((total, fee) => total + Math.round(fee * 100) / 100, 0);
18529
18638
  };
18530
18639
  var getPlaceOrderContainerClassName = () => {
18531
18640
  return PLACE_ORDER_CONTAINER_CLASS_NAME;
@@ -18787,7 +18896,7 @@ var buildLiveRouteCards = ({
18787
18896
  // balance condition, and `handleExecuteQuote` rejects an empty quoteId.
18788
18897
  sq.venue !== primaryWinnerVenue
18789
18898
  ).map((sq) => {
18790
- var _a2;
18899
+ var _a2, _b2;
18791
18900
  const parsedVenue = parseVenue(sq.venue);
18792
18901
  const venue = parsedVenue.success ? parsedVenue.data : void 0;
18793
18902
  if (geoBlockedVenues.has(sq.venue)) {
@@ -18820,7 +18929,12 @@ var buildLiveRouteCards = ({
18820
18929
  estimatedProfit: sq.estimatedProfit,
18821
18930
  returnPct: sq.returnPct,
18822
18931
  // venueSoloQuotes stripped on solo card's quoteData (only the primary needs them)
18823
- venueSoloQuotes: void 0
18932
+ venueSoloQuotes: void 0,
18933
+ // This solo's OWN fee breakdown. Without it the spread above leaves the
18934
+ // primary route's breakdown in place, so selecting a bridge-free venue
18935
+ // still showed the primary's bridging charge. Falls back to the
18936
+ // primary only when the router omitted one (non-"ok" solos).
18937
+ feeBreakdown: (_b2 = sq.feeBreakdown) != null ? _b2 : quoteData.feeBreakdown
18824
18938
  }), sq.quoteId ? { status: "ok", error: void 0 } : null);
18825
18939
  return {
18826
18940
  id: `live-solo-${sq.venue}`,
@@ -21698,6 +21812,14 @@ var PlaceOrder = ({
21698
21812
  enabled: Boolean(isAuthenticated && isSell),
21699
21813
  mode: isPaperMode ? "paper" : void 0
21700
21814
  });
21815
+ const sellableSharesByVenue = (0, import_react35.useMemo)(
21816
+ () => isSell ? resolveSellableSharesByVenue({
21817
+ positions: executionPositions,
21818
+ market: scopedSelectedMarket,
21819
+ selectedOutcome: scopedSelectedOutcome
21820
+ }) : /* @__PURE__ */ new Map(),
21821
+ [executionPositions, isSell, scopedSelectedMarket, scopedSelectedOutcome]
21822
+ );
21701
21823
  const isSmartRouteEnabled = !isLimitOrder && isQuotePanelActive && !isEndedWithoutKnownWinner && !submissionProgressState && !isBeforeActionPending && !executeManaged.isPending && debouncedAmount > 0 && orderEligibility.canPlaceOrder && // On the sell tab, hold the quote until the amount has been initialized
21702
21824
  // from the user's position for THIS outcome AND the debounced value has
21703
21825
  // caught up to it. The amount input is shared with the buy tab, so right
@@ -21748,13 +21870,26 @@ var PlaceOrder = ({
21748
21870
  }, [limitVenueQuotes.quotes]);
21749
21871
  const availableLimitVenueOptions = (0, import_react35.useMemo)(() => {
21750
21872
  return visibleLimitVenueOptions.filter((option) => {
21751
- return !geoBlockedLimitVenues.has(option.venue) && (0, import_hooks63.getVenueAvailabilityState)({
21873
+ var _a2;
21874
+ return !geoBlockedLimitVenues.has(option.venue) && // A limit SELL rests against shares held at that specific venue, so a
21875
+ // venue the user has no position on is a guaranteed 409 from the
21876
+ // server's reservation check — and the automatic pick, which sorts on
21877
+ // price alone, would happily choose one. Only narrow once we know
21878
+ // where the shares are; an empty map means positions haven't resolved.
21879
+ (!isSell || sellableSharesByVenue.size === 0 || ((_a2 = sellableSharesByVenue.get(option.venue)) != null ? _a2 : 0) > 0) && (0, import_hooks63.getVenueAvailabilityState)({
21752
21880
  venueId: option.venue,
21753
21881
  disabledVenues,
21754
21882
  isConfigLoading: isAppConfigLoading
21755
21883
  }) === "available";
21756
21884
  });
21757
- }, [disabledVenues, geoBlockedLimitVenues, isAppConfigLoading, visibleLimitVenueOptions]);
21885
+ }, [
21886
+ disabledVenues,
21887
+ geoBlockedLimitVenues,
21888
+ isAppConfigLoading,
21889
+ isSell,
21890
+ sellableSharesByVenue,
21891
+ visibleLimitVenueOptions
21892
+ ]);
21758
21893
  const automaticLimitVenueOption = (0, import_react35.useMemo)(
21759
21894
  () => resolveAutomaticLimitOrderVenueOption(availableLimitVenueOptions, internalTab),
21760
21895
  [availableLimitVenueOptions, internalTab]
@@ -21856,39 +21991,15 @@ var PlaceOrder = ({
21856
21991
  refreshContext: smartRouteRefreshContext
21857
21992
  });
21858
21993
  const currentSellableShares = (0, import_react35.useMemo)(() => {
21859
- var _a2, _b2, _c2, _d2, _e2, _f2, _g2;
21994
+ var _a2, _b2;
21860
21995
  const sharesFromQuote = (_b2 = (_a2 = smartRoute.data) == null ? void 0 : _a2.positionAvailability) == null ? void 0 : _b2.totalSellableShares;
21861
21996
  if (typeof sharesFromQuote === "number" && Number.isFinite(sharesFromQuote)) {
21862
21997
  return Math.max(0, sharesFromQuote);
21863
21998
  }
21864
- if (!isSell || !scopedSelectedOutcome || !scopedSelectedMarket) return 0;
21865
- const normalizedSelectedOutcomeLabel = scopedSelectedOutcome.label.trim().toLowerCase();
21866
- const selectedMarketIds = [
21867
- scopedSelectedMarket.id,
21868
- (_c2 = scopedSelectedMarket.marketId) != null ? _c2 : void 0,
21869
- (_d2 = scopedSelectedMarket.externalIdentifier) != null ? _d2 : void 0
21870
- ].filter((value) => Boolean(value));
21871
- const selectedMarketIdSet = new Set(selectedMarketIds);
21872
21999
  let resolvedShares = 0;
21873
- for (const group of executionPositions) {
21874
- const groupOutcomes = (_f2 = (_e2 = group.venueMarket) == null ? void 0 : _e2.venueMarketOutcomes) != null ? _f2 : [];
21875
- for (const outcome of groupOutcomes) {
21876
- if (outcome.label.trim().toLowerCase() !== normalizedSelectedOutcomeLabel) continue;
21877
- for (const breakdown of (_g2 = outcome.venueBreakdown) != null ? _g2 : []) {
21878
- const matchesMarketId = selectedMarketIdSet.size === 0 || selectedMarketIdSet.has(group.targetMarketId) || selectedMarketIdSet.has(breakdown.venueMarketId);
21879
- if (!matchesMarketId) continue;
21880
- resolvedShares += Number.isFinite(breakdown.size) ? breakdown.size : 0;
21881
- }
21882
- }
21883
- }
22000
+ for (const size of sellableSharesByVenue.values()) resolvedShares += size;
21884
22001
  return Math.max(0, resolvedShares);
21885
- }, [
21886
- executionPositions,
21887
- isSell,
21888
- scopedSelectedMarket,
21889
- scopedSelectedOutcome,
21890
- (_q = (_p = smartRoute.data) == null ? void 0 : _p.positionAvailability) == null ? void 0 : _q.totalSellableShares
21891
- ]);
22002
+ }, [sellableSharesByVenue, (_q = (_p = smartRoute.data) == null ? void 0 : _p.positionAvailability) == null ? void 0 : _q.totalSellableShares]);
21892
22003
  const maxSellableShares = (0, import_react35.useMemo)(
21893
22004
  () => floorToDecimals(currentSellableShares, SELL_SHARE_INPUT_DECIMALS),
21894
22005
  [currentSellableShares]
@@ -27283,6 +27394,85 @@ var resolveInitialTabValue = (tabs, defaultActiveTab) => {
27283
27394
  return (_b = (_a = tabs[0]) == null ? void 0 : _a.value) != null ? _b : ALL_CATEGORIES_TAB_VALUE;
27284
27395
  };
27285
27396
 
27397
+ // src/pages/home/event-discovery-url-state.ts
27398
+ var import_zod2 = require("zod");
27399
+ var nonEmptyParamSchema = import_zod2.z.string().trim().min(1);
27400
+ var sortParamSchema = import_zod2.z.enum(EVENT_LIST_SORT_VALUES);
27401
+ var readScalarParam = (searchParams, name, schema) => {
27402
+ const values = searchParams.getAll(name);
27403
+ if (values.length === 0) return { invalid: false };
27404
+ if (values.length !== 1) return { invalid: true };
27405
+ const parsedValue = schema.safeParse(values[0]);
27406
+ if (!parsedValue.success) return { invalid: true };
27407
+ return { value: parsedValue.data, invalid: false };
27408
+ };
27409
+ var readEventDiscoveryUrlState = (searchParams) => {
27410
+ const category = readScalarParam(searchParams, "category", nonEmptyParamSchema);
27411
+ const venue = readScalarParam(searchParams, "venue", nonEmptyParamSchema);
27412
+ const sort = readScalarParam(searchParams, "sort", sortParamSchema);
27413
+ const subcategoryPath = [];
27414
+ let hasInvalidSubcategory = false;
27415
+ for (const value of searchParams.getAll("subcategory")) {
27416
+ const parsedValue = nonEmptyParamSchema.safeParse(value);
27417
+ if (!parsedValue.success) {
27418
+ hasInvalidSubcategory = true;
27419
+ break;
27420
+ }
27421
+ subcategoryPath.push(parsedValue.data);
27422
+ }
27423
+ return {
27424
+ category: category.value,
27425
+ subcategoryPath,
27426
+ venue: venue.value,
27427
+ sort: sort.value,
27428
+ categoryIsInvalid: category.invalid,
27429
+ shouldCanonicalize: category.invalid || venue.invalid || sort.invalid || hasInvalidSubcategory
27430
+ };
27431
+ };
27432
+ var resolveEventDiscoveryUrlState = ({
27433
+ parsedState,
27434
+ categoryValues,
27435
+ venueValues,
27436
+ defaultCategory,
27437
+ defaultVenue
27438
+ }) => {
27439
+ var _a, _b, _c;
27440
+ const categoryIsValid = parsedState.category == null || categoryValues.includes(parsedState.category);
27441
+ const venueIsValid = parsedState.venue == null || venueValues.includes(parsedState.venue);
27442
+ const category = categoryIsValid ? (_a = parsedState.category) != null ? _a : defaultCategory : defaultCategory;
27443
+ const venue = venueIsValid ? (_b = parsedState.venue) != null ? _b : defaultVenue : defaultVenue;
27444
+ const sort = (_c = parsedState.sort) != null ? _c : DEFAULT_EVENT_LIST_SORT;
27445
+ return {
27446
+ state: {
27447
+ category,
27448
+ subcategoryPath: categoryIsValid && !parsedState.categoryIsInvalid ? parsedState.subcategoryPath : [],
27449
+ venue,
27450
+ sort
27451
+ },
27452
+ shouldCanonicalize: parsedState.shouldCanonicalize || !categoryIsValid || !venueIsValid || parsedState.category === defaultCategory || parsedState.venue === defaultVenue || parsedState.sort === DEFAULT_EVENT_LIST_SORT
27453
+ };
27454
+ };
27455
+ var buildEventDiscoveryUrl = ({
27456
+ currentUrl,
27457
+ state,
27458
+ defaultCategory,
27459
+ defaultVenue
27460
+ }) => {
27461
+ const nextUrl = new URL(currentUrl.toString());
27462
+ nextUrl.searchParams.delete("category");
27463
+ nextUrl.searchParams.delete("subcategory");
27464
+ nextUrl.searchParams.delete("venue");
27465
+ nextUrl.searchParams.delete("sort");
27466
+ if (state.category !== defaultCategory) nextUrl.searchParams.set("category", state.category);
27467
+ for (const subcategory of state.subcategoryPath) {
27468
+ nextUrl.searchParams.append("subcategory", subcategory);
27469
+ }
27470
+ if (state.venue !== defaultVenue) nextUrl.searchParams.set("venue", state.venue);
27471
+ if (state.sort !== DEFAULT_EVENT_LIST_SORT) nextUrl.searchParams.set("sort", state.sort);
27472
+ const search = nextUrl.searchParams.toString();
27473
+ return `${nextUrl.pathname}${search ? `?${search}` : ""}${nextUrl.hash}`;
27474
+ };
27475
+
27286
27476
  // src/pages/home/use-scroll-restoration.ts
27287
27477
  var import_react43 = require("react");
27288
27478
  function useScrollRestoration({
@@ -27562,7 +27752,7 @@ var HomePage = ({
27562
27752
  onError,
27563
27753
  stickyOrderPanel
27564
27754
  }) => {
27565
- var _a, _b, _c, _d;
27755
+ var _a, _b, _c, _d, _e, _f, _g;
27566
27756
  const labels = (0, import_hooks71.useLabels)();
27567
27757
  const {
27568
27758
  search: {
@@ -27572,8 +27762,11 @@ var HomePage = ({
27572
27762
  onChange: onSearchChange,
27573
27763
  onSelect: onSelectEventInternal
27574
27764
  },
27575
- trading: { executionMode }
27765
+ trading: { executionMode },
27766
+ features: { enableEventDiscoveryUrlPersistence }
27576
27767
  } = (0, import_hooks71.useSdkUiConfig)();
27768
+ const { isLoading: isAppConfigLoading } = (0, import_hooks71.useAppConfig)();
27769
+ const primaryEventListTabs = useEventListTabs();
27577
27770
  const { capture, consume } = (0, import_hooks71.useEventListState)();
27578
27771
  const [snapshot] = (0, import_react45.useState)(() => consume());
27579
27772
  const eventListStateRef = (0, import_react45.useRef)(null);
@@ -27644,7 +27837,7 @@ var HomePage = ({
27644
27837
  }, [isShowingAllResults, normalizedSearchValue, selectedEvent]);
27645
27838
  const resolvedSelectedEvent = selectedEvent != null ? selectedEvent : stickySelectedEvent;
27646
27839
  const resolvedAllCategoryTabLabel = allCategoryTabLabel === DEFAULT_ALL_CATEGORY_TAB_LABEL ? labels.home.trending : allCategoryTabLabel;
27647
- const { categories } = (0, import_hooks71.useCategories)({
27840
+ const { categories, isLoading: isCategoriesLoading } = (0, import_hooks71.useCategories)({
27648
27841
  limit: categoriesLimit,
27649
27842
  enabled: !hasCustomTabs
27650
27843
  });
@@ -27655,22 +27848,180 @@ var HomePage = ({
27655
27848
  if (hasCustomTabs && tabs) return tabs;
27656
27849
  return categoryTabs;
27657
27850
  }, [categoryTabs, hasCustomTabs, tabs]);
27851
+ const availableCategoryValues = (0, import_react45.useMemo)(
27852
+ () => resolvedTabs.filter((tab) => !tab.disabled).map((tab) => tab.value),
27853
+ [resolvedTabs]
27854
+ );
27855
+ const resolvedDefaultCategory = resolveInitialTabValue(resolvedTabs, defaultActiveTab);
27856
+ const defaultCategory = availableCategoryValues.includes(resolvedDefaultCategory) ? resolvedDefaultCategory : (_a = availableCategoryValues[0]) != null ? _a : resolvedDefaultCategory;
27857
+ const availableVenueTabs = (0, import_react45.useMemo)(
27858
+ () => primaryEventListTabs.filter((tab) => !tab.disabled && !tab.isComingSoon),
27859
+ [primaryEventListTabs]
27860
+ );
27861
+ const availableVenueValues = (0, import_react45.useMemo)(
27862
+ () => availableVenueTabs.map((tab) => tab.value),
27863
+ [availableVenueTabs]
27864
+ );
27865
+ const defaultVenue = (_c = (_b = availableVenueTabs[0]) == null ? void 0 : _b.value) != null ? _c : "matched";
27658
27866
  const resolvedEventSectionItems = eventSectionItems && eventSectionItems.length > 0 ? eventSectionItems : getDefaultEventSectionItems(labels);
27659
- const [activeTabValue, setActiveTabValue] = (0, import_react45.useState)(() => {
27660
- if (snapshot == null ? void 0 : snapshot.categoryTab) {
27661
- return snapshot.categoryTab;
27867
+ const [discoveryFilterState, setDiscoveryFilterState] = (0, import_react45.useState)(
27868
+ () => {
27869
+ var _a2, _b2;
27870
+ return {
27871
+ category: (_a2 = snapshot == null ? void 0 : snapshot.categoryTab) != null ? _a2 : defaultCategory,
27872
+ venue: (_b2 = snapshot == null ? void 0 : snapshot.venueTab) != null ? _b2 : defaultVenue,
27873
+ sort: DEFAULT_EVENT_LIST_SORT,
27874
+ subcategoryPath: []
27875
+ };
27662
27876
  }
27663
- return resolveInitialTabValue(resolvedTabs, defaultActiveTab);
27664
- });
27877
+ );
27878
+ const discoveryFilterStateRef = (0, import_react45.useRef)(discoveryFilterState);
27879
+ discoveryFilterStateRef.current = discoveryFilterState;
27880
+ const [isUrlStateReady, setIsUrlStateReady] = (0, import_react45.useState)(!enableEventDiscoveryUrlPersistence);
27881
+ const hasInitializedUrlStateRef = (0, import_react45.useRef)(false);
27882
+ const activeTabValue = discoveryFilterState.category;
27883
+ const resolveCurrentUrlState = (0, import_react45.useCallback)(() => {
27884
+ if (typeof window === "undefined") return null;
27885
+ const parsedState = readEventDiscoveryUrlState(new URL(window.location.href).searchParams);
27886
+ const resolvedState = resolveEventDiscoveryUrlState({
27887
+ parsedState,
27888
+ categoryValues: availableCategoryValues,
27889
+ venueValues: availableVenueValues,
27890
+ defaultCategory,
27891
+ defaultVenue
27892
+ });
27893
+ return {
27894
+ state: {
27895
+ category: resolvedState.state.category,
27896
+ venue: resolvedState.state.venue,
27897
+ sort: resolvedState.state.sort,
27898
+ subcategoryPath: resolvedState.state.subcategoryPath.map((id) => ({
27899
+ id,
27900
+ label: id,
27901
+ eventCount: 0
27902
+ }))
27903
+ },
27904
+ shouldCanonicalize: resolvedState.shouldCanonicalize
27905
+ };
27906
+ }, [availableCategoryValues, availableVenueValues, defaultCategory, defaultVenue]);
27907
+ const writeFilterStateToHistory = (0, import_react45.useCallback)(
27908
+ (state, historyMode) => {
27909
+ if (!enableEventDiscoveryUrlPersistence || typeof window === "undefined") return;
27910
+ const currentUrl = new URL(window.location.href);
27911
+ const nextUrl = buildEventDiscoveryUrl({
27912
+ currentUrl,
27913
+ state: {
27914
+ category: state.category,
27915
+ venue: state.venue,
27916
+ sort: state.sort,
27917
+ subcategoryPath: state.subcategoryPath.map((entry) => entry.id)
27918
+ },
27919
+ defaultCategory,
27920
+ defaultVenue
27921
+ });
27922
+ const currentRelativeUrl = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;
27923
+ if (nextUrl === currentRelativeUrl) return;
27924
+ const method = historyMode === "push" ? "pushState" : "replaceState";
27925
+ window.history[method](window.history.state, "", nextUrl);
27926
+ },
27927
+ [defaultCategory, defaultVenue, enableEventDiscoveryUrlPersistence]
27928
+ );
27929
+ const commitDiscoveryFilterState = (0, import_react45.useCallback)(
27930
+ (state, historyMode) => {
27931
+ discoveryFilterStateRef.current = state;
27932
+ setDiscoveryFilterState(state);
27933
+ if (isUrlStateReady) writeFilterStateToHistory(state, historyMode);
27934
+ },
27935
+ [isUrlStateReady, writeFilterStateToHistory]
27936
+ );
27937
+ (0, import_react45.useEffect)(() => {
27938
+ if (!enableEventDiscoveryUrlPersistence) {
27939
+ hasInitializedUrlStateRef.current = false;
27940
+ setIsUrlStateReady(true);
27941
+ return;
27942
+ }
27943
+ if (hasInitializedUrlStateRef.current) return;
27944
+ if (!hasCustomTabs && isCategoriesLoading || isAppConfigLoading) return;
27945
+ const resolvedUrlState = resolveCurrentUrlState();
27946
+ if (!resolvedUrlState) return;
27947
+ hasInitializedUrlStateRef.current = true;
27948
+ discoveryFilterStateRef.current = resolvedUrlState.state;
27949
+ setDiscoveryFilterState(resolvedUrlState.state);
27950
+ setIsUrlStateReady(true);
27951
+ const currentUrl = new URL(window.location.href);
27952
+ const canonicalUrl = buildEventDiscoveryUrl({
27953
+ currentUrl,
27954
+ state: {
27955
+ category: resolvedUrlState.state.category,
27956
+ venue: resolvedUrlState.state.venue,
27957
+ sort: resolvedUrlState.state.sort,
27958
+ subcategoryPath: resolvedUrlState.state.subcategoryPath.map((entry) => entry.id)
27959
+ },
27960
+ defaultCategory,
27961
+ defaultVenue
27962
+ });
27963
+ const currentRelativeUrl = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;
27964
+ if (resolvedUrlState.shouldCanonicalize || canonicalUrl !== currentRelativeUrl) {
27965
+ window.history.replaceState(window.history.state, "", canonicalUrl);
27966
+ }
27967
+ }, [
27968
+ defaultCategory,
27969
+ defaultVenue,
27970
+ enableEventDiscoveryUrlPersistence,
27971
+ hasCustomTabs,
27972
+ isAppConfigLoading,
27973
+ isCategoriesLoading,
27974
+ resolveCurrentUrlState
27975
+ ]);
27976
+ (0, import_react45.useEffect)(() => {
27977
+ if (!enableEventDiscoveryUrlPersistence || !isUrlStateReady) return;
27978
+ const handlePopState = () => {
27979
+ const resolvedUrlState = resolveCurrentUrlState();
27980
+ if (!resolvedUrlState) return;
27981
+ discoveryFilterStateRef.current = resolvedUrlState.state;
27982
+ setDiscoveryFilterState(resolvedUrlState.state);
27983
+ if (resolvedUrlState.shouldCanonicalize) {
27984
+ writeFilterStateToHistory(resolvedUrlState.state, "replace");
27985
+ }
27986
+ };
27987
+ window.addEventListener("popstate", handlePopState);
27988
+ return () => {
27989
+ window.removeEventListener("popstate", handlePopState);
27990
+ };
27991
+ }, [
27992
+ enableEventDiscoveryUrlPersistence,
27993
+ isUrlStateReady,
27994
+ resolveCurrentUrlState,
27995
+ writeFilterStateToHistory
27996
+ ]);
27665
27997
  const activeTabValueRef = (0, import_react45.useRef)(activeTabValue);
27666
27998
  activeTabValueRef.current = activeTabValue;
27667
27999
  (0, import_react45.useEffect)(() => {
27668
- setActiveTabValue((currentValue) => {
27669
- const hasCurrentValue = resolvedTabs.some((tab) => tab.value === currentValue);
27670
- if (hasCurrentValue) return currentValue;
27671
- return resolveInitialTabValue(resolvedTabs, defaultActiveTab);
28000
+ if (enableEventDiscoveryUrlPersistence && !isUrlStateReady) return;
28001
+ const currentState = discoveryFilterStateRef.current;
28002
+ const categoryIsAvailable = availableCategoryValues.includes(currentState.category);
28003
+ const venueIsAvailable = availableVenueValues.includes(currentState.venue);
28004
+ if (categoryIsAvailable && (!enableEventDiscoveryUrlPersistence || venueIsAvailable)) return;
28005
+ const nextState = __spreadProps(__spreadValues({}, currentState), {
28006
+ category: categoryIsAvailable ? currentState.category : defaultCategory,
28007
+ venue: venueIsAvailable ? currentState.venue : defaultVenue,
28008
+ subcategoryPath: categoryIsAvailable ? currentState.subcategoryPath : []
27672
28009
  });
27673
- }, [defaultActiveTab, resolvedTabs]);
28010
+ if (enableEventDiscoveryUrlPersistence) {
28011
+ commitDiscoveryFilterState(nextState, "replace");
28012
+ return;
28013
+ }
28014
+ discoveryFilterStateRef.current = nextState;
28015
+ setDiscoveryFilterState(nextState);
28016
+ }, [
28017
+ availableCategoryValues,
28018
+ availableVenueValues,
28019
+ commitDiscoveryFilterState,
28020
+ defaultCategory,
28021
+ defaultVenue,
28022
+ enableEventDiscoveryUrlPersistence,
28023
+ isUrlStateReady
28024
+ ]);
27674
28025
  const tabsItems = (0, import_react45.useMemo)(() => {
27675
28026
  return resolvedTabs.map((tab) => {
27676
28027
  const isActive = tab.value === activeTabValue;
@@ -27711,7 +28062,13 @@ var HomePage = ({
27711
28062
  ];
27712
28063
  }, [activeTab, activeTabValue, resolvedEventSectionItems]);
27713
28064
  const handleTabChange = (value) => {
27714
- setActiveTabValue(value);
28065
+ commitDiscoveryFilterState(
28066
+ __spreadProps(__spreadValues({}, discoveryFilterStateRef.current), {
28067
+ category: value,
28068
+ subcategoryPath: []
28069
+ }),
28070
+ "push"
28071
+ );
27715
28072
  _onTabChange == null ? void 0 : _onTabChange(value);
27716
28073
  };
27717
28074
  const handleCategoryRootChange = (categoryId) => {
@@ -27733,10 +28090,10 @@ var HomePage = ({
27733
28090
  handleSelectEvent(event);
27734
28091
  };
27735
28092
  const shouldRenderMobileSearch = isMobileSearchViewport && !resolvedSelectedEvent;
27736
- const isScrollRestorationReady = !!snapshot && !isShowingAllResults && !resolvedSelectedEvent && ((_b = (_a = eventListStateRef.current) == null ? void 0 : _a.loadedPageCount) != null ? _b : 0) >= ((_c = snapshot.loadedPageCount) != null ? _c : 1);
28093
+ const isScrollRestorationReady = !!snapshot && !isShowingAllResults && !resolvedSelectedEvent && ((_e = (_d = eventListStateRef.current) == null ? void 0 : _d.loadedPageCount) != null ? _e : 0) >= ((_f = snapshot.loadedPageCount) != null ? _f : 1);
27737
28094
  useScrollRestoration({
27738
28095
  enabled: !!snapshot && snapshot.scrollY > 0,
27739
- scrollY: (_d = snapshot == null ? void 0 : snapshot.scrollY) != null ? _d : 0,
28096
+ scrollY: (_g = snapshot == null ? void 0 : snapshot.scrollY) != null ? _g : 0,
27740
28097
  isReady: isScrollRestorationReady
27741
28098
  });
27742
28099
  return /* @__PURE__ */ (0, import_jsx_runtime168.jsx)(AggErrorBoundary, { onError, children: /* @__PURE__ */ (0, import_jsx_runtime168.jsxs)("section", { className: cn("agg-home-page flex w-full flex-col", classNames == null ? void 0 : classNames.root), children: [
@@ -27818,7 +28175,13 @@ var HomePage = ({
27818
28175
  "div",
27819
28176
  {
27820
28177
  className: "agg-home-section",
27821
- children: /* @__PURE__ */ (0, import_jsx_runtime168.jsx)(
28178
+ children: sectionIndex === 0 && !isUrlStateReady ? /* @__PURE__ */ (0, import_jsx_runtime168.jsx)(
28179
+ Skeleton,
28180
+ {
28181
+ view: "event-list",
28182
+ ariaLabel: labels.eventList.loading(eventSectionItem.title)
28183
+ }
28184
+ ) : /* @__PURE__ */ (0, import_jsx_runtime168.jsx)(
27822
28185
  EventList,
27823
28186
  __spreadValues({
27824
28187
  title: eventSectionItem.title,
@@ -27834,11 +28197,33 @@ var HomePage = ({
27834
28197
  handleSelectEvent(event);
27835
28198
  },
27836
28199
  onMarketClick: onMarketClickProp
27837
- }, sectionIndex === 0 ? {
28200
+ }, sectionIndex === 0 ? __spreadValues({
27838
28201
  stateRef: eventListStateRef,
27839
- initialVenueTab: (_d2 = snapshot == null ? void 0 : snapshot.venueTab) != null ? _d2 : void 0,
28202
+ initialVenueTab: enableEventDiscoveryUrlPersistence ? void 0 : (_d2 = snapshot == null ? void 0 : snapshot.venueTab) != null ? _d2 : void 0,
27840
28203
  initialLoadedPageCount: snapshot == null ? void 0 : snapshot.loadedPageCount
27841
- } : void 0)
28204
+ }, enableEventDiscoveryUrlPersistence ? {
28205
+ activeVenueTab: discoveryFilterState.venue,
28206
+ onActiveVenueTabChange: (venue) => {
28207
+ commitDiscoveryFilterState(
28208
+ __spreadProps(__spreadValues({}, discoveryFilterStateRef.current), { venue }),
28209
+ "push"
28210
+ );
28211
+ },
28212
+ selectedSort: discoveryFilterState.sort,
28213
+ onSelectedSortChange: (sort) => {
28214
+ commitDiscoveryFilterState(
28215
+ __spreadProps(__spreadValues({}, discoveryFilterStateRef.current), { sort }),
28216
+ "push"
28217
+ );
28218
+ },
28219
+ categoryPath: discoveryFilterState.subcategoryPath,
28220
+ onCategoryPathChange: (subcategoryPath, options) => {
28221
+ commitDiscoveryFilterState(
28222
+ __spreadProps(__spreadValues({}, discoveryFilterStateRef.current), { subcategoryPath }),
28223
+ options.history
28224
+ );
28225
+ }
28226
+ } : void 0) : void 0)
27842
28227
  )
27843
28228
  },
27844
28229
  `${(_a2 = eventSectionItem.id) != null ? _a2 : eventSectionItem.title}-${sectionIndex}`
@@ -28198,7 +28583,7 @@ var import_hooks74 = require("@agg-build/hooks");
28198
28583
  var import_sdk26 = require("@agg-build/sdk");
28199
28584
  var Dialog8 = __toESM(require("@radix-ui/react-dialog"));
28200
28585
  var import_react46 = require("react");
28201
- var import_zod2 = require("zod");
28586
+ var import_zod3 = require("zod");
28202
28587
  var import_jsx_runtime171 = require("react/jsx-runtime");
28203
28588
  var USDC_DECIMALS = 6;
28204
28589
  var EDITABLE_AMOUNT_PATTERN = /^\d*(?:\.\d{0,6})?$/;
@@ -28223,7 +28608,7 @@ var VENUE_LABELS = {
28223
28608
  [import_sdk26.Venue.hyperliquid]: "Hyperliquid",
28224
28609
  [import_sdk26.Venue.novig]: "Novig"
28225
28610
  };
28226
- var amountSchema = import_zod2.z.string().min(1).regex(FINAL_AMOUNT_PATTERN);
28611
+ var amountSchema = import_zod3.z.string().min(1).regex(FINAL_AMOUNT_PATTERN);
28227
28612
  var decimalToRaw = (value, decimals = USDC_DECIMALS) => {
28228
28613
  const parsed = amountSchema.safeParse(value.trim());
28229
28614
  if (!parsed.success) return null;