@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/index.js CHANGED
@@ -5653,6 +5653,19 @@ var resolveCategoryIdsFromPath = (path, fallbackCategoryIds) => {
5653
5653
  if (deepest) return [deepest];
5654
5654
  return fallbackCategoryIds;
5655
5655
  };
5656
+ var validateSubcategoryPath = (requestedPath, rootCategoryId, childrenByParentId) => {
5657
+ var _a;
5658
+ if (!rootCategoryId) return [];
5659
+ const validPath = [];
5660
+ let parentId = rootCategoryId;
5661
+ for (const categoryId of requestedPath) {
5662
+ const category = (_a = childrenByParentId.get(parentId)) == null ? void 0 : _a.find((child) => child.id === categoryId);
5663
+ if (!category) break;
5664
+ validPath.push(category.id);
5665
+ parentId = category.id;
5666
+ }
5667
+ return validPath;
5668
+ };
5656
5669
  var resolveTabVenus = (tab, visibleVenues) => {
5657
5670
  const applyAllowList = (venues) => {
5658
5671
  if (!venues) {
@@ -18460,6 +18473,13 @@ var import_react30 = require("react");
18460
18473
  // src/events/list/event-list.constants.ts
18461
18474
  var import_sdk16 = require("@agg-build/sdk");
18462
18475
  var DEFAULT_EVENTS_LIMIT = 50;
18476
+ var DEFAULT_EVENT_LIST_SORT = "volume24hr";
18477
+ var EVENT_LIST_SORT_VALUES = [
18478
+ "volume24hr",
18479
+ "topArbitrage",
18480
+ "volume",
18481
+ "endDate"
18482
+ ];
18463
18483
  var getDefaultEventListTabs = (labels) => {
18464
18484
  return [
18465
18485
  {
@@ -18529,6 +18549,7 @@ var getDefaultEventListTabs = (labels) => {
18529
18549
 
18530
18550
  // src/events/list/event-list-tabs.tsx
18531
18551
  var import_jsx_runtime155 = require("react/jsx-runtime");
18552
+ var DEFAULT_HIDDEN_VENUES = new Set((0, import_sdk17.getEffectiveDisabledVenues)(void 0));
18532
18553
  var renderTabIcon = (tab, isActive) => {
18533
18554
  if (tab.iconName === "warning-filled") {
18534
18555
  return /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(Icon, { name: "warning-filled", size: "small", color: "currentColor" });
@@ -18557,15 +18578,11 @@ var useEventListTabs = (tabs) => {
18557
18578
  const availabilityState = (0, import_hooks55.getVenueAvailabilityState)({
18558
18579
  venueId: tab.venueLogo,
18559
18580
  disabledVenues,
18560
- // A compile-time-inactive venue (novig today) is hidden by default and
18561
- // un-hidden per-environment by NOVIG_DATA_VISIBLE, so its
18562
- // disabled-ness is only known once `/app/config` resolves — treating
18563
- // it as hidden while that request is in flight stops its tab flashing
18564
- // in and out where the flag is unset. Active venues must NOT be
18565
- // withheld, or they pop in late. Keyed off the shared inactive-venue
18566
- // helper rather than a venue name, so launching or retiring one needs
18567
- // no change here.
18568
- isConfigLoading: isAppConfigLoading && (0, import_sdk17.isVenueInactive)(tab.venueLogo),
18581
+ // A globally inactive or default-disabled venue is hidden until
18582
+ // `/app/config` resolves. That prevents partner-opt-in venues such as
18583
+ // Novig from flashing briefly for apps that still disable them, while
18584
+ // ordinary active venues continue rendering immediately.
18585
+ isConfigLoading: isAppConfigLoading && ((0, import_sdk17.isVenueInactive)(tab.venueLogo) || DEFAULT_HIDDEN_VENUES.has(tab.venueLogo)),
18569
18586
  isLocationBlocked
18570
18587
  });
18571
18588
  if (availabilityState === "hidden") return [];
@@ -18743,10 +18760,16 @@ var EventList = ({
18743
18760
  getMarketHref,
18744
18761
  getEventHref,
18745
18762
  initialVenueTab,
18763
+ activeVenueTab: controlledActiveVenueTab,
18764
+ onActiveVenueTabChange,
18765
+ selectedSort: controlledSelectedSort,
18766
+ onSelectedSortChange,
18767
+ categoryPath: controlledCategoryPath,
18768
+ onCategoryPathChange,
18746
18769
  initialLoadedPageCount,
18747
18770
  stateRef
18748
18771
  }) => {
18749
- var _a, _b, _c, _d, _e;
18772
+ var _a, _b, _c, _d, _e, _f;
18750
18773
  const labels = (0, import_hooks56.useLabels)();
18751
18774
  const { disabledVenues } = (0, import_hooks56.useAppConfig)();
18752
18775
  const {
@@ -18758,13 +18781,37 @@ var EventList = ({
18758
18781
  () => disabledVenues.length === 0 ? void 0 : (0, import_hooks56.getVisibleVenueIdsByConfig)(import_sdk18.VENUES, disabledVenues),
18759
18782
  [disabledVenues]
18760
18783
  );
18761
- const [activeTabValue, setActiveTabValue] = (0, import_react31.useState)(
18784
+ const [internalActiveTabValue, setInternalActiveTabValue] = (0, import_react31.useState)(
18762
18785
  (_b = initialVenueTab != null ? initialVenueTab : (_a = resolvedTabs[0]) == null ? void 0 : _a.value) != null ? _b : "matched"
18763
18786
  );
18764
- const [selectedSort, setSelectedSort] = (0, import_react31.useState)("volume24hr");
18787
+ const activeTabValue = controlledActiveVenueTab != null ? controlledActiveVenueTab : internalActiveTabValue;
18788
+ const [internalSelectedSort, setInternalSelectedSort] = (0, import_react31.useState)(DEFAULT_EVENT_LIST_SORT);
18789
+ const selectedSort = controlledSelectedSort != null ? controlledSelectedSort : internalSelectedSort;
18765
18790
  const [isSubcategoriesModalOpen, setIsSubcategoriesModalOpen] = (0, import_react31.useState)(false);
18766
- const [categoryPath, setCategoryPath] = (0, import_react31.useState)([]);
18791
+ const [internalCategoryPath, setInternalCategoryPath] = (0, import_react31.useState)([]);
18792
+ const categoryPath = controlledCategoryPath != null ? controlledCategoryPath : internalCategoryPath;
18767
18793
  const [collapsedCategoryIds, setCollapsedCategoryIds] = (0, import_react31.useState)(() => /* @__PURE__ */ new Set());
18794
+ const handleActiveTabChange = (0, import_react31.useCallback)(
18795
+ (value) => {
18796
+ if (controlledActiveVenueTab == null) setInternalActiveTabValue(value);
18797
+ onActiveVenueTabChange == null ? void 0 : onActiveVenueTabChange(value, { history: "push" });
18798
+ },
18799
+ [controlledActiveVenueTab, onActiveVenueTabChange]
18800
+ );
18801
+ const handleSelectedSortChange = (0, import_react31.useCallback)(
18802
+ (value) => {
18803
+ if (controlledSelectedSort == null) setInternalSelectedSort(value);
18804
+ onSelectedSortChange == null ? void 0 : onSelectedSortChange(value, { history: "push" });
18805
+ },
18806
+ [controlledSelectedSort, onSelectedSortChange]
18807
+ );
18808
+ const handleCategoryPathChange = (0, import_react31.useCallback)(
18809
+ (value, options) => {
18810
+ if (controlledCategoryPath == null) setInternalCategoryPath(value);
18811
+ onCategoryPathChange == null ? void 0 : onCategoryPathChange(value, options);
18812
+ },
18813
+ [controlledCategoryPath, onCategoryPathChange]
18814
+ );
18768
18815
  const sortItems = (0, import_react31.useMemo)(() => {
18769
18816
  return [
18770
18817
  {
@@ -18797,9 +18844,9 @@ var EventList = ({
18797
18844
  const baseCategoryId = (_c = categoryIds == null ? void 0 : categoryIds[0]) != null ? _c : null;
18798
18845
  (0, import_react31.useEffect)(() => {
18799
18846
  if (!isDiscoveryFiltersEnabled) return;
18800
- setCategoryPath([]);
18847
+ if (controlledCategoryPath == null) setInternalCategoryPath([]);
18801
18848
  setCollapsedCategoryIds(/* @__PURE__ */ new Set());
18802
- }, [baseCategoryId, isDiscoveryFiltersEnabled]);
18849
+ }, [baseCategoryId, controlledCategoryPath, isDiscoveryFiltersEnabled]);
18803
18850
  const { categories: topLevelCategories } = (0, import_hooks56.useCategories)({
18804
18851
  queryKeyScope: "event-list-top-categories",
18805
18852
  enabled: isDiscoveryFiltersEnabled,
@@ -18811,12 +18858,13 @@ var EventList = ({
18811
18858
  const baseCategoryChildPrefetchIds = (0, import_react31.useMemo)(() => {
18812
18859
  return Array.from(
18813
18860
  /* @__PURE__ */ new Set([
18861
+ ...baseCategoryId ? [baseCategoryId] : [],
18814
18862
  ...sortedTopLevelCategories.map((category) => category.id),
18815
18863
  ...categoryPath.map((category) => category.id)
18816
18864
  ])
18817
18865
  );
18818
- }, [categoryPath, sortedTopLevelCategories]);
18819
- const { childrenByParentId: baseChildrenByParentId } = (0, import_hooks56.useCategoryChildren)({
18866
+ }, [baseCategoryId, categoryPath, sortedTopLevelCategories]);
18867
+ const { childrenByParentId: baseChildrenByParentId, isLoading: isBaseCategoryChildrenLoading } = (0, import_hooks56.useCategoryChildren)({
18820
18868
  queryKeyScope: "event-list-category-children",
18821
18869
  enabled: isDiscoveryFiltersEnabled,
18822
18870
  parentIds: baseCategoryChildPrefetchIds,
@@ -18866,7 +18914,36 @@ var EventList = ({
18866
18914
  ...visibleGrandchildrenByParentId
18867
18915
  ]);
18868
18916
  }, [baseChildrenByParentId, visibleChildrenByParentId, visibleGrandchildrenByParentId]);
18869
- const shouldRenderSubcategoryFilters = isDiscoveryFiltersEnabled && baseCategoryId !== null && (((_e = (_d = childrenByParentId.get(baseCategoryId)) == null ? void 0 : _d.length) != null ? _e : 0) > 0 || categoryPath.length > 0);
18917
+ const controlledCategoryPathKey = (_d = controlledCategoryPath == null ? void 0 : controlledCategoryPath.map((entry) => entry.id).join(",")) != null ? _d : "";
18918
+ const controlledCategoryPathValidationKey = `${baseCategoryId != null ? baseCategoryId : ""}|${controlledCategoryPathKey}`;
18919
+ const [validatedCategoryPathKey, setValidatedCategoryPathKey] = (0, import_react31.useState)(
18920
+ () => controlledCategoryPath == null || controlledCategoryPath.length === 0 ? controlledCategoryPathValidationKey : ""
18921
+ );
18922
+ (0, import_react31.useEffect)(() => {
18923
+ if (controlledCategoryPath == null || controlledCategoryPath.length === 0) {
18924
+ setValidatedCategoryPathKey(controlledCategoryPathValidationKey);
18925
+ return;
18926
+ }
18927
+ if (isBaseCategoryChildrenLoading) return;
18928
+ const requestedIds = controlledCategoryPath.map((entry) => entry.id);
18929
+ const validIds = validateSubcategoryPath(requestedIds, baseCategoryId, baseChildrenByParentId);
18930
+ if (validIds.length !== requestedIds.length) {
18931
+ handleCategoryPathChange(controlledCategoryPath.slice(0, validIds.length), {
18932
+ history: "replace"
18933
+ });
18934
+ return;
18935
+ }
18936
+ setValidatedCategoryPathKey(controlledCategoryPathValidationKey);
18937
+ }, [
18938
+ baseCategoryId,
18939
+ baseChildrenByParentId,
18940
+ controlledCategoryPath,
18941
+ controlledCategoryPathKey,
18942
+ controlledCategoryPathValidationKey,
18943
+ handleCategoryPathChange,
18944
+ isBaseCategoryChildrenLoading
18945
+ ]);
18946
+ const shouldRenderSubcategoryFilters = isDiscoveryFiltersEnabled && baseCategoryId !== null && (((_f = (_e = childrenByParentId.get(baseCategoryId)) == null ? void 0 : _e.length) != null ? _f : 0) > 0 || categoryPath.length > 0);
18870
18947
  const baseCategoryEventCount = (0, import_react31.useMemo)(() => {
18871
18948
  var _a2, _b2;
18872
18949
  return (_b2 = (_a2 = sortedTopLevelCategories.find((c) => c.id === baseCategoryId)) == null ? void 0 : _a2.eventCount) != null ? _b2 : 0;
@@ -18924,7 +19001,8 @@ var EventList = ({
18924
19001
  // markets experience is enabled (the sports event-detail view loads the
18925
19002
  // folded companions via aggKey). Gated on the same flag as that view.
18926
19003
  grouped: showSportsMarkets,
18927
- initialPages: initialLoadedPageCount
19004
+ initialPages: initialLoadedPageCount,
19005
+ enabled: controlledCategoryPath == null || validatedCategoryPathKey === controlledCategoryPathValidationKey
18928
19006
  });
18929
19007
  (0, import_react31.useEffect)(() => {
18930
19008
  if (stateRef) {
@@ -18985,7 +19063,7 @@ var EventList = ({
18985
19063
  "grid grid-cols-[repeat(auto-fill,minmax(240px,1fr))] md:grid-cols-[repeat(auto-fill,minmax(360px,1fr))] gap-4"
18986
19064
  );
18987
19065
  const handleSelectAllCategories = () => {
18988
- setCategoryPath([]);
19066
+ handleCategoryPathChange([], { history: "push" });
18989
19067
  setCollapsedCategoryIds(/* @__PURE__ */ new Set());
18990
19068
  onCategoryRootChange == null ? void 0 : onCategoryRootChange(baseCategoryId != null ? baseCategoryId : void 0);
18991
19069
  setIsSubcategoriesModalOpen(false);
@@ -18997,7 +19075,7 @@ var EventList = ({
18997
19075
  isExpanded,
18998
19076
  isSelected
18999
19077
  }) => {
19000
- setCategoryPath((prev) => [...prev.slice(0, depth), entry]);
19078
+ handleCategoryPathChange([...categoryPath.slice(0, depth), entry], { history: "push" });
19001
19079
  setCollapsedCategoryIds((prev) => {
19002
19080
  const next = new Set(prev);
19003
19081
  if (hasKnownChildren && isExpanded && isSelected) {
@@ -19037,7 +19115,7 @@ var EventList = ({
19037
19115
  ariaLabel: labels.eventList.tabsAria(title2),
19038
19116
  className: "agg-event-list-tabs min-w-0 flex-1 max-w-[600px]!",
19039
19117
  activeTab: activeTabValue,
19040
- onTabChange: setActiveTabValue,
19118
+ onTabChange: handleActiveTabChange,
19041
19119
  overflowBehavior: "scroll"
19042
19120
  }
19043
19121
  ),
@@ -19047,7 +19125,7 @@ var EventList = ({
19047
19125
  ariaLabel: labels.eventList.sortByLabel,
19048
19126
  className: "min-w-[200px] w-auto! shrink-0 min-h-10.5",
19049
19127
  value: selectedSort,
19050
- onChange: setSelectedSort,
19128
+ onChange: handleSelectedSortChange,
19051
19129
  items: sortItems,
19052
19130
  contentClassName: "py-2",
19053
19131
  triggerClassName: "rounded-agg-lg!"
@@ -19064,7 +19142,7 @@ var EventList = ({
19064
19142
  ariaLabel: labels.eventList.tabsAria(title2),
19065
19143
  className: "agg-event-list-tabs min-w-0 flex-1",
19066
19144
  activeTab: activeTabValue,
19067
- onTabChange: setActiveTabValue,
19145
+ onTabChange: handleActiveTabChange,
19068
19146
  overflowBehavior: "select"
19069
19147
  }
19070
19148
  ),
@@ -19074,7 +19152,7 @@ var EventList = ({
19074
19152
  ariaLabel: labels.eventList.sortByLabel,
19075
19153
  className: "min-w-0 flex-1 md:min-w-[144px]",
19076
19154
  value: selectedSort,
19077
- onChange: setSelectedSort,
19155
+ onChange: handleSelectedSortChange,
19078
19156
  items: sortItems,
19079
19157
  contentClassName: "rounded-[12px] py-2 shadow-[0_8px_16px_rgba(0,0,0,0.1)]"
19080
19158
  }
@@ -20666,6 +20744,37 @@ var findMatchingVenueOutcome = (market, selectedOutcome) => {
20666
20744
  return normalizedLabel !== "" && selectedNames.has(normalizedLabel);
20667
20745
  })) != null ? _b : null;
20668
20746
  };
20747
+ var resolveSellableSharesByVenue = ({
20748
+ positions,
20749
+ market,
20750
+ selectedOutcome
20751
+ }) => {
20752
+ var _a, _b, _c, _d, _e, _f, _g;
20753
+ const sharesByVenue = /* @__PURE__ */ new Map();
20754
+ if (!market || !selectedOutcome) return sharesByVenue;
20755
+ const normalizedSelectedOutcomeLabel = normalizeOutcomeName(selectedOutcome.label);
20756
+ const selectedMarketIdSet = new Set(
20757
+ [
20758
+ market.id,
20759
+ (_a = market.marketId) != null ? _a : void 0,
20760
+ (_b = market.externalIdentifier) != null ? _b : void 0,
20761
+ ...((_c = market.matchedVenueMarkets) != null ? _c : []).map((matched) => matched.id)
20762
+ ].filter((value) => Boolean(value))
20763
+ );
20764
+ for (const group of positions) {
20765
+ for (const outcome of (_e = (_d = group.venueMarket) == null ? void 0 : _d.venueMarketOutcomes) != null ? _e : []) {
20766
+ if (normalizeOutcomeName(outcome.label) !== normalizedSelectedOutcomeLabel) continue;
20767
+ for (const breakdown of (_f = outcome.venueBreakdown) != null ? _f : []) {
20768
+ const matchesMarketId = selectedMarketIdSet.size === 0 || selectedMarketIdSet.has(group.targetMarketId) || selectedMarketIdSet.has(breakdown.venueMarketId);
20769
+ if (!matchesMarketId) continue;
20770
+ const size = Number.isFinite(breakdown.size) ? breakdown.size : 0;
20771
+ if (size <= 0) continue;
20772
+ sharesByVenue.set(breakdown.venue, ((_g = sharesByVenue.get(breakdown.venue)) != null ? _g : 0) + size);
20773
+ }
20774
+ }
20775
+ }
20776
+ return sharesByVenue;
20777
+ };
20669
20778
  var buildLimitOrderVenueOptions = ({
20670
20779
  currentPrices,
20671
20780
  livePrices,
@@ -20750,7 +20859,7 @@ var getSmartRouteTotalFees = (feeBreakdown) => {
20750
20859
  if (!feeBreakdown) return null;
20751
20860
  const feeParts = [feeBreakdown.venueFees, feeBreakdown.bridgeFees, feeBreakdown.executionGas];
20752
20861
  if (!feeParts.every(Number.isFinite)) return null;
20753
- return feeParts.reduce((total, fee) => total + fee, 0);
20862
+ return feeParts.reduce((total, fee) => total + Math.round(fee * 100) / 100, 0);
20754
20863
  };
20755
20864
  var getPlaceOrderContainerClassName = () => {
20756
20865
  return PLACE_ORDER_CONTAINER_CLASS_NAME;
@@ -21012,7 +21121,7 @@ var buildLiveRouteCards = ({
21012
21121
  // balance condition, and `handleExecuteQuote` rejects an empty quoteId.
21013
21122
  sq.venue !== primaryWinnerVenue
21014
21123
  ).map((sq) => {
21015
- var _a2;
21124
+ var _a2, _b2;
21016
21125
  const parsedVenue = parseVenue(sq.venue);
21017
21126
  const venue = parsedVenue.success ? parsedVenue.data : void 0;
21018
21127
  if (geoBlockedVenues.has(sq.venue)) {
@@ -21045,7 +21154,12 @@ var buildLiveRouteCards = ({
21045
21154
  estimatedProfit: sq.estimatedProfit,
21046
21155
  returnPct: sq.returnPct,
21047
21156
  // venueSoloQuotes stripped on solo card's quoteData (only the primary needs them)
21048
- venueSoloQuotes: void 0
21157
+ venueSoloQuotes: void 0,
21158
+ // This solo's OWN fee breakdown. Without it the spread above leaves the
21159
+ // primary route's breakdown in place, so selecting a bridge-free venue
21160
+ // still showed the primary's bridging charge. Falls back to the
21161
+ // primary only when the router omitted one (non-"ok" solos).
21162
+ feeBreakdown: (_b2 = sq.feeBreakdown) != null ? _b2 : quoteData.feeBreakdown
21049
21163
  }), sq.quoteId ? { status: "ok", error: void 0 } : null);
21050
21164
  return {
21051
21165
  id: `live-solo-${sq.venue}`,
@@ -23923,6 +24037,14 @@ var PlaceOrder = ({
23923
24037
  enabled: Boolean(isAuthenticated && isSell),
23924
24038
  mode: isPaperMode ? "paper" : void 0
23925
24039
  });
24040
+ const sellableSharesByVenue = (0, import_react38.useMemo)(
24041
+ () => isSell ? resolveSellableSharesByVenue({
24042
+ positions: executionPositions,
24043
+ market: scopedSelectedMarket,
24044
+ selectedOutcome: scopedSelectedOutcome
24045
+ }) : /* @__PURE__ */ new Map(),
24046
+ [executionPositions, isSell, scopedSelectedMarket, scopedSelectedOutcome]
24047
+ );
23926
24048
  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
23927
24049
  // from the user's position for THIS outcome AND the debounced value has
23928
24050
  // caught up to it. The amount input is shared with the buy tab, so right
@@ -23973,13 +24095,26 @@ var PlaceOrder = ({
23973
24095
  }, [limitVenueQuotes.quotes]);
23974
24096
  const availableLimitVenueOptions = (0, import_react38.useMemo)(() => {
23975
24097
  return visibleLimitVenueOptions.filter((option) => {
23976
- return !geoBlockedLimitVenues.has(option.venue) && (0, import_hooks66.getVenueAvailabilityState)({
24098
+ var _a2;
24099
+ return !geoBlockedLimitVenues.has(option.venue) && // A limit SELL rests against shares held at that specific venue, so a
24100
+ // venue the user has no position on is a guaranteed 409 from the
24101
+ // server's reservation check — and the automatic pick, which sorts on
24102
+ // price alone, would happily choose one. Only narrow once we know
24103
+ // where the shares are; an empty map means positions haven't resolved.
24104
+ (!isSell || sellableSharesByVenue.size === 0 || ((_a2 = sellableSharesByVenue.get(option.venue)) != null ? _a2 : 0) > 0) && (0, import_hooks66.getVenueAvailabilityState)({
23977
24105
  venueId: option.venue,
23978
24106
  disabledVenues,
23979
24107
  isConfigLoading: isAppConfigLoading
23980
24108
  }) === "available";
23981
24109
  });
23982
- }, [disabledVenues, geoBlockedLimitVenues, isAppConfigLoading, visibleLimitVenueOptions]);
24110
+ }, [
24111
+ disabledVenues,
24112
+ geoBlockedLimitVenues,
24113
+ isAppConfigLoading,
24114
+ isSell,
24115
+ sellableSharesByVenue,
24116
+ visibleLimitVenueOptions
24117
+ ]);
23983
24118
  const automaticLimitVenueOption = (0, import_react38.useMemo)(
23984
24119
  () => resolveAutomaticLimitOrderVenueOption(availableLimitVenueOptions, internalTab),
23985
24120
  [availableLimitVenueOptions, internalTab]
@@ -24081,39 +24216,15 @@ var PlaceOrder = ({
24081
24216
  refreshContext: smartRouteRefreshContext
24082
24217
  });
24083
24218
  const currentSellableShares = (0, import_react38.useMemo)(() => {
24084
- var _a2, _b2, _c2, _d2, _e2, _f2, _g2;
24219
+ var _a2, _b2;
24085
24220
  const sharesFromQuote = (_b2 = (_a2 = smartRoute.data) == null ? void 0 : _a2.positionAvailability) == null ? void 0 : _b2.totalSellableShares;
24086
24221
  if (typeof sharesFromQuote === "number" && Number.isFinite(sharesFromQuote)) {
24087
24222
  return Math.max(0, sharesFromQuote);
24088
24223
  }
24089
- if (!isSell || !scopedSelectedOutcome || !scopedSelectedMarket) return 0;
24090
- const normalizedSelectedOutcomeLabel = scopedSelectedOutcome.label.trim().toLowerCase();
24091
- const selectedMarketIds = [
24092
- scopedSelectedMarket.id,
24093
- (_c2 = scopedSelectedMarket.marketId) != null ? _c2 : void 0,
24094
- (_d2 = scopedSelectedMarket.externalIdentifier) != null ? _d2 : void 0
24095
- ].filter((value) => Boolean(value));
24096
- const selectedMarketIdSet = new Set(selectedMarketIds);
24097
24224
  let resolvedShares = 0;
24098
- for (const group of executionPositions) {
24099
- const groupOutcomes = (_f2 = (_e2 = group.venueMarket) == null ? void 0 : _e2.venueMarketOutcomes) != null ? _f2 : [];
24100
- for (const outcome of groupOutcomes) {
24101
- if (outcome.label.trim().toLowerCase() !== normalizedSelectedOutcomeLabel) continue;
24102
- for (const breakdown of (_g2 = outcome.venueBreakdown) != null ? _g2 : []) {
24103
- const matchesMarketId = selectedMarketIdSet.size === 0 || selectedMarketIdSet.has(group.targetMarketId) || selectedMarketIdSet.has(breakdown.venueMarketId);
24104
- if (!matchesMarketId) continue;
24105
- resolvedShares += Number.isFinite(breakdown.size) ? breakdown.size : 0;
24106
- }
24107
- }
24108
- }
24225
+ for (const size of sellableSharesByVenue.values()) resolvedShares += size;
24109
24226
  return Math.max(0, resolvedShares);
24110
- }, [
24111
- executionPositions,
24112
- isSell,
24113
- scopedSelectedMarket,
24114
- scopedSelectedOutcome,
24115
- (_q = (_p = smartRoute.data) == null ? void 0 : _p.positionAvailability) == null ? void 0 : _q.totalSellableShares
24116
- ]);
24227
+ }, [sellableSharesByVenue, (_q = (_p = smartRoute.data) == null ? void 0 : _p.positionAvailability) == null ? void 0 : _q.totalSellableShares]);
24117
24228
  const maxSellableShares = (0, import_react38.useMemo)(
24118
24229
  () => floorToDecimals(currentSellableShares, SELL_SHARE_INPUT_DECIMALS),
24119
24230
  [currentSellableShares]
@@ -29508,6 +29619,85 @@ var resolveInitialTabValue = (tabs, defaultActiveTab) => {
29508
29619
  return (_b = (_a = tabs[0]) == null ? void 0 : _a.value) != null ? _b : ALL_CATEGORIES_TAB_VALUE;
29509
29620
  };
29510
29621
 
29622
+ // src/pages/home/event-discovery-url-state.ts
29623
+ var import_zod2 = require("zod");
29624
+ var nonEmptyParamSchema = import_zod2.z.string().trim().min(1);
29625
+ var sortParamSchema = import_zod2.z.enum(EVENT_LIST_SORT_VALUES);
29626
+ var readScalarParam = (searchParams, name, schema) => {
29627
+ const values = searchParams.getAll(name);
29628
+ if (values.length === 0) return { invalid: false };
29629
+ if (values.length !== 1) return { invalid: true };
29630
+ const parsedValue = schema.safeParse(values[0]);
29631
+ if (!parsedValue.success) return { invalid: true };
29632
+ return { value: parsedValue.data, invalid: false };
29633
+ };
29634
+ var readEventDiscoveryUrlState = (searchParams) => {
29635
+ const category = readScalarParam(searchParams, "category", nonEmptyParamSchema);
29636
+ const venue = readScalarParam(searchParams, "venue", nonEmptyParamSchema);
29637
+ const sort = readScalarParam(searchParams, "sort", sortParamSchema);
29638
+ const subcategoryPath = [];
29639
+ let hasInvalidSubcategory = false;
29640
+ for (const value of searchParams.getAll("subcategory")) {
29641
+ const parsedValue = nonEmptyParamSchema.safeParse(value);
29642
+ if (!parsedValue.success) {
29643
+ hasInvalidSubcategory = true;
29644
+ break;
29645
+ }
29646
+ subcategoryPath.push(parsedValue.data);
29647
+ }
29648
+ return {
29649
+ category: category.value,
29650
+ subcategoryPath,
29651
+ venue: venue.value,
29652
+ sort: sort.value,
29653
+ categoryIsInvalid: category.invalid,
29654
+ shouldCanonicalize: category.invalid || venue.invalid || sort.invalid || hasInvalidSubcategory
29655
+ };
29656
+ };
29657
+ var resolveEventDiscoveryUrlState = ({
29658
+ parsedState,
29659
+ categoryValues,
29660
+ venueValues,
29661
+ defaultCategory,
29662
+ defaultVenue
29663
+ }) => {
29664
+ var _a, _b, _c;
29665
+ const categoryIsValid = parsedState.category == null || categoryValues.includes(parsedState.category);
29666
+ const venueIsValid = parsedState.venue == null || venueValues.includes(parsedState.venue);
29667
+ const category = categoryIsValid ? (_a = parsedState.category) != null ? _a : defaultCategory : defaultCategory;
29668
+ const venue = venueIsValid ? (_b = parsedState.venue) != null ? _b : defaultVenue : defaultVenue;
29669
+ const sort = (_c = parsedState.sort) != null ? _c : DEFAULT_EVENT_LIST_SORT;
29670
+ return {
29671
+ state: {
29672
+ category,
29673
+ subcategoryPath: categoryIsValid && !parsedState.categoryIsInvalid ? parsedState.subcategoryPath : [],
29674
+ venue,
29675
+ sort
29676
+ },
29677
+ shouldCanonicalize: parsedState.shouldCanonicalize || !categoryIsValid || !venueIsValid || parsedState.category === defaultCategory || parsedState.venue === defaultVenue || parsedState.sort === DEFAULT_EVENT_LIST_SORT
29678
+ };
29679
+ };
29680
+ var buildEventDiscoveryUrl = ({
29681
+ currentUrl,
29682
+ state,
29683
+ defaultCategory,
29684
+ defaultVenue
29685
+ }) => {
29686
+ const nextUrl = new URL(currentUrl.toString());
29687
+ nextUrl.searchParams.delete("category");
29688
+ nextUrl.searchParams.delete("subcategory");
29689
+ nextUrl.searchParams.delete("venue");
29690
+ nextUrl.searchParams.delete("sort");
29691
+ if (state.category !== defaultCategory) nextUrl.searchParams.set("category", state.category);
29692
+ for (const subcategory of state.subcategoryPath) {
29693
+ nextUrl.searchParams.append("subcategory", subcategory);
29694
+ }
29695
+ if (state.venue !== defaultVenue) nextUrl.searchParams.set("venue", state.venue);
29696
+ if (state.sort !== DEFAULT_EVENT_LIST_SORT) nextUrl.searchParams.set("sort", state.sort);
29697
+ const search = nextUrl.searchParams.toString();
29698
+ return `${nextUrl.pathname}${search ? `?${search}` : ""}${nextUrl.hash}`;
29699
+ };
29700
+
29511
29701
  // src/pages/home/use-scroll-restoration.ts
29512
29702
  var import_react46 = require("react");
29513
29703
  function useScrollRestoration({
@@ -29787,7 +29977,7 @@ var HomePage = ({
29787
29977
  onError,
29788
29978
  stickyOrderPanel
29789
29979
  }) => {
29790
- var _a, _b, _c, _d;
29980
+ var _a, _b, _c, _d, _e, _f, _g;
29791
29981
  const labels = (0, import_hooks74.useLabels)();
29792
29982
  const {
29793
29983
  search: {
@@ -29797,8 +29987,11 @@ var HomePage = ({
29797
29987
  onChange: onSearchChange,
29798
29988
  onSelect: onSelectEventInternal
29799
29989
  },
29800
- trading: { executionMode }
29990
+ trading: { executionMode },
29991
+ features: { enableEventDiscoveryUrlPersistence }
29801
29992
  } = (0, import_hooks74.useSdkUiConfig)();
29993
+ const { isLoading: isAppConfigLoading } = (0, import_hooks74.useAppConfig)();
29994
+ const primaryEventListTabs = useEventListTabs();
29802
29995
  const { capture, consume } = (0, import_hooks74.useEventListState)();
29803
29996
  const [snapshot] = (0, import_react48.useState)(() => consume());
29804
29997
  const eventListStateRef = (0, import_react48.useRef)(null);
@@ -29869,7 +30062,7 @@ var HomePage = ({
29869
30062
  }, [isShowingAllResults, normalizedSearchValue, selectedEvent]);
29870
30063
  const resolvedSelectedEvent = selectedEvent != null ? selectedEvent : stickySelectedEvent;
29871
30064
  const resolvedAllCategoryTabLabel = allCategoryTabLabel === DEFAULT_ALL_CATEGORY_TAB_LABEL ? labels.home.trending : allCategoryTabLabel;
29872
- const { categories } = (0, import_hooks74.useCategories)({
30065
+ const { categories, isLoading: isCategoriesLoading } = (0, import_hooks74.useCategories)({
29873
30066
  limit: categoriesLimit,
29874
30067
  enabled: !hasCustomTabs
29875
30068
  });
@@ -29880,22 +30073,180 @@ var HomePage = ({
29880
30073
  if (hasCustomTabs && tabs) return tabs;
29881
30074
  return categoryTabs;
29882
30075
  }, [categoryTabs, hasCustomTabs, tabs]);
30076
+ const availableCategoryValues = (0, import_react48.useMemo)(
30077
+ () => resolvedTabs.filter((tab) => !tab.disabled).map((tab) => tab.value),
30078
+ [resolvedTabs]
30079
+ );
30080
+ const resolvedDefaultCategory = resolveInitialTabValue(resolvedTabs, defaultActiveTab);
30081
+ const defaultCategory = availableCategoryValues.includes(resolvedDefaultCategory) ? resolvedDefaultCategory : (_a = availableCategoryValues[0]) != null ? _a : resolvedDefaultCategory;
30082
+ const availableVenueTabs = (0, import_react48.useMemo)(
30083
+ () => primaryEventListTabs.filter((tab) => !tab.disabled && !tab.isComingSoon),
30084
+ [primaryEventListTabs]
30085
+ );
30086
+ const availableVenueValues = (0, import_react48.useMemo)(
30087
+ () => availableVenueTabs.map((tab) => tab.value),
30088
+ [availableVenueTabs]
30089
+ );
30090
+ const defaultVenue = (_c = (_b = availableVenueTabs[0]) == null ? void 0 : _b.value) != null ? _c : "matched";
29883
30091
  const resolvedEventSectionItems = eventSectionItems && eventSectionItems.length > 0 ? eventSectionItems : getDefaultEventSectionItems(labels);
29884
- const [activeTabValue, setActiveTabValue] = (0, import_react48.useState)(() => {
29885
- if (snapshot == null ? void 0 : snapshot.categoryTab) {
29886
- return snapshot.categoryTab;
30092
+ const [discoveryFilterState, setDiscoveryFilterState] = (0, import_react48.useState)(
30093
+ () => {
30094
+ var _a2, _b2;
30095
+ return {
30096
+ category: (_a2 = snapshot == null ? void 0 : snapshot.categoryTab) != null ? _a2 : defaultCategory,
30097
+ venue: (_b2 = snapshot == null ? void 0 : snapshot.venueTab) != null ? _b2 : defaultVenue,
30098
+ sort: DEFAULT_EVENT_LIST_SORT,
30099
+ subcategoryPath: []
30100
+ };
29887
30101
  }
29888
- return resolveInitialTabValue(resolvedTabs, defaultActiveTab);
29889
- });
30102
+ );
30103
+ const discoveryFilterStateRef = (0, import_react48.useRef)(discoveryFilterState);
30104
+ discoveryFilterStateRef.current = discoveryFilterState;
30105
+ const [isUrlStateReady, setIsUrlStateReady] = (0, import_react48.useState)(!enableEventDiscoveryUrlPersistence);
30106
+ const hasInitializedUrlStateRef = (0, import_react48.useRef)(false);
30107
+ const activeTabValue = discoveryFilterState.category;
30108
+ const resolveCurrentUrlState = (0, import_react48.useCallback)(() => {
30109
+ if (typeof window === "undefined") return null;
30110
+ const parsedState = readEventDiscoveryUrlState(new URL(window.location.href).searchParams);
30111
+ const resolvedState = resolveEventDiscoveryUrlState({
30112
+ parsedState,
30113
+ categoryValues: availableCategoryValues,
30114
+ venueValues: availableVenueValues,
30115
+ defaultCategory,
30116
+ defaultVenue
30117
+ });
30118
+ return {
30119
+ state: {
30120
+ category: resolvedState.state.category,
30121
+ venue: resolvedState.state.venue,
30122
+ sort: resolvedState.state.sort,
30123
+ subcategoryPath: resolvedState.state.subcategoryPath.map((id) => ({
30124
+ id,
30125
+ label: id,
30126
+ eventCount: 0
30127
+ }))
30128
+ },
30129
+ shouldCanonicalize: resolvedState.shouldCanonicalize
30130
+ };
30131
+ }, [availableCategoryValues, availableVenueValues, defaultCategory, defaultVenue]);
30132
+ const writeFilterStateToHistory = (0, import_react48.useCallback)(
30133
+ (state, historyMode) => {
30134
+ if (!enableEventDiscoveryUrlPersistence || typeof window === "undefined") return;
30135
+ const currentUrl = new URL(window.location.href);
30136
+ const nextUrl = buildEventDiscoveryUrl({
30137
+ currentUrl,
30138
+ state: {
30139
+ category: state.category,
30140
+ venue: state.venue,
30141
+ sort: state.sort,
30142
+ subcategoryPath: state.subcategoryPath.map((entry) => entry.id)
30143
+ },
30144
+ defaultCategory,
30145
+ defaultVenue
30146
+ });
30147
+ const currentRelativeUrl = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;
30148
+ if (nextUrl === currentRelativeUrl) return;
30149
+ const method = historyMode === "push" ? "pushState" : "replaceState";
30150
+ window.history[method](window.history.state, "", nextUrl);
30151
+ },
30152
+ [defaultCategory, defaultVenue, enableEventDiscoveryUrlPersistence]
30153
+ );
30154
+ const commitDiscoveryFilterState = (0, import_react48.useCallback)(
30155
+ (state, historyMode) => {
30156
+ discoveryFilterStateRef.current = state;
30157
+ setDiscoveryFilterState(state);
30158
+ if (isUrlStateReady) writeFilterStateToHistory(state, historyMode);
30159
+ },
30160
+ [isUrlStateReady, writeFilterStateToHistory]
30161
+ );
30162
+ (0, import_react48.useEffect)(() => {
30163
+ if (!enableEventDiscoveryUrlPersistence) {
30164
+ hasInitializedUrlStateRef.current = false;
30165
+ setIsUrlStateReady(true);
30166
+ return;
30167
+ }
30168
+ if (hasInitializedUrlStateRef.current) return;
30169
+ if (!hasCustomTabs && isCategoriesLoading || isAppConfigLoading) return;
30170
+ const resolvedUrlState = resolveCurrentUrlState();
30171
+ if (!resolvedUrlState) return;
30172
+ hasInitializedUrlStateRef.current = true;
30173
+ discoveryFilterStateRef.current = resolvedUrlState.state;
30174
+ setDiscoveryFilterState(resolvedUrlState.state);
30175
+ setIsUrlStateReady(true);
30176
+ const currentUrl = new URL(window.location.href);
30177
+ const canonicalUrl = buildEventDiscoveryUrl({
30178
+ currentUrl,
30179
+ state: {
30180
+ category: resolvedUrlState.state.category,
30181
+ venue: resolvedUrlState.state.venue,
30182
+ sort: resolvedUrlState.state.sort,
30183
+ subcategoryPath: resolvedUrlState.state.subcategoryPath.map((entry) => entry.id)
30184
+ },
30185
+ defaultCategory,
30186
+ defaultVenue
30187
+ });
30188
+ const currentRelativeUrl = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`;
30189
+ if (resolvedUrlState.shouldCanonicalize || canonicalUrl !== currentRelativeUrl) {
30190
+ window.history.replaceState(window.history.state, "", canonicalUrl);
30191
+ }
30192
+ }, [
30193
+ defaultCategory,
30194
+ defaultVenue,
30195
+ enableEventDiscoveryUrlPersistence,
30196
+ hasCustomTabs,
30197
+ isAppConfigLoading,
30198
+ isCategoriesLoading,
30199
+ resolveCurrentUrlState
30200
+ ]);
30201
+ (0, import_react48.useEffect)(() => {
30202
+ if (!enableEventDiscoveryUrlPersistence || !isUrlStateReady) return;
30203
+ const handlePopState = () => {
30204
+ const resolvedUrlState = resolveCurrentUrlState();
30205
+ if (!resolvedUrlState) return;
30206
+ discoveryFilterStateRef.current = resolvedUrlState.state;
30207
+ setDiscoveryFilterState(resolvedUrlState.state);
30208
+ if (resolvedUrlState.shouldCanonicalize) {
30209
+ writeFilterStateToHistory(resolvedUrlState.state, "replace");
30210
+ }
30211
+ };
30212
+ window.addEventListener("popstate", handlePopState);
30213
+ return () => {
30214
+ window.removeEventListener("popstate", handlePopState);
30215
+ };
30216
+ }, [
30217
+ enableEventDiscoveryUrlPersistence,
30218
+ isUrlStateReady,
30219
+ resolveCurrentUrlState,
30220
+ writeFilterStateToHistory
30221
+ ]);
29890
30222
  const activeTabValueRef = (0, import_react48.useRef)(activeTabValue);
29891
30223
  activeTabValueRef.current = activeTabValue;
29892
30224
  (0, import_react48.useEffect)(() => {
29893
- setActiveTabValue((currentValue) => {
29894
- const hasCurrentValue = resolvedTabs.some((tab) => tab.value === currentValue);
29895
- if (hasCurrentValue) return currentValue;
29896
- return resolveInitialTabValue(resolvedTabs, defaultActiveTab);
30225
+ if (enableEventDiscoveryUrlPersistence && !isUrlStateReady) return;
30226
+ const currentState = discoveryFilterStateRef.current;
30227
+ const categoryIsAvailable = availableCategoryValues.includes(currentState.category);
30228
+ const venueIsAvailable = availableVenueValues.includes(currentState.venue);
30229
+ if (categoryIsAvailable && (!enableEventDiscoveryUrlPersistence || venueIsAvailable)) return;
30230
+ const nextState = __spreadProps(__spreadValues({}, currentState), {
30231
+ category: categoryIsAvailable ? currentState.category : defaultCategory,
30232
+ venue: venueIsAvailable ? currentState.venue : defaultVenue,
30233
+ subcategoryPath: categoryIsAvailable ? currentState.subcategoryPath : []
29897
30234
  });
29898
- }, [defaultActiveTab, resolvedTabs]);
30235
+ if (enableEventDiscoveryUrlPersistence) {
30236
+ commitDiscoveryFilterState(nextState, "replace");
30237
+ return;
30238
+ }
30239
+ discoveryFilterStateRef.current = nextState;
30240
+ setDiscoveryFilterState(nextState);
30241
+ }, [
30242
+ availableCategoryValues,
30243
+ availableVenueValues,
30244
+ commitDiscoveryFilterState,
30245
+ defaultCategory,
30246
+ defaultVenue,
30247
+ enableEventDiscoveryUrlPersistence,
30248
+ isUrlStateReady
30249
+ ]);
29899
30250
  const tabsItems = (0, import_react48.useMemo)(() => {
29900
30251
  return resolvedTabs.map((tab) => {
29901
30252
  const isActive = tab.value === activeTabValue;
@@ -29936,7 +30287,13 @@ var HomePage = ({
29936
30287
  ];
29937
30288
  }, [activeTab, activeTabValue, resolvedEventSectionItems]);
29938
30289
  const handleTabChange = (value) => {
29939
- setActiveTabValue(value);
30290
+ commitDiscoveryFilterState(
30291
+ __spreadProps(__spreadValues({}, discoveryFilterStateRef.current), {
30292
+ category: value,
30293
+ subcategoryPath: []
30294
+ }),
30295
+ "push"
30296
+ );
29940
30297
  _onTabChange == null ? void 0 : _onTabChange(value);
29941
30298
  };
29942
30299
  const handleCategoryRootChange = (categoryId) => {
@@ -29958,10 +30315,10 @@ var HomePage = ({
29958
30315
  handleSelectEvent(event);
29959
30316
  };
29960
30317
  const shouldRenderMobileSearch = isMobileSearchViewport && !resolvedSelectedEvent;
29961
- const isScrollRestorationReady = !!snapshot && !isShowingAllResults && !resolvedSelectedEvent && ((_b = (_a = eventListStateRef.current) == null ? void 0 : _a.loadedPageCount) != null ? _b : 0) >= ((_c = snapshot.loadedPageCount) != null ? _c : 1);
30318
+ const isScrollRestorationReady = !!snapshot && !isShowingAllResults && !resolvedSelectedEvent && ((_e = (_d = eventListStateRef.current) == null ? void 0 : _d.loadedPageCount) != null ? _e : 0) >= ((_f = snapshot.loadedPageCount) != null ? _f : 1);
29962
30319
  useScrollRestoration({
29963
30320
  enabled: !!snapshot && snapshot.scrollY > 0,
29964
- scrollY: (_d = snapshot == null ? void 0 : snapshot.scrollY) != null ? _d : 0,
30321
+ scrollY: (_g = snapshot == null ? void 0 : snapshot.scrollY) != null ? _g : 0,
29965
30322
  isReady: isScrollRestorationReady
29966
30323
  });
29967
30324
  return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(AggErrorBoundary, { onError, children: /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)("section", { className: cn("agg-home-page flex w-full flex-col", classNames == null ? void 0 : classNames.root), children: [
@@ -30043,7 +30400,13 @@ var HomePage = ({
30043
30400
  "div",
30044
30401
  {
30045
30402
  className: "agg-home-section",
30046
- children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
30403
+ children: sectionIndex === 0 && !isUrlStateReady ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
30404
+ Skeleton,
30405
+ {
30406
+ view: "event-list",
30407
+ ariaLabel: labels.eventList.loading(eventSectionItem.title)
30408
+ }
30409
+ ) : /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
30047
30410
  EventList,
30048
30411
  __spreadValues({
30049
30412
  title: eventSectionItem.title,
@@ -30059,11 +30422,33 @@ var HomePage = ({
30059
30422
  handleSelectEvent(event);
30060
30423
  },
30061
30424
  onMarketClick: onMarketClickProp
30062
- }, sectionIndex === 0 ? {
30425
+ }, sectionIndex === 0 ? __spreadValues({
30063
30426
  stateRef: eventListStateRef,
30064
- initialVenueTab: (_d2 = snapshot == null ? void 0 : snapshot.venueTab) != null ? _d2 : void 0,
30427
+ initialVenueTab: enableEventDiscoveryUrlPersistence ? void 0 : (_d2 = snapshot == null ? void 0 : snapshot.venueTab) != null ? _d2 : void 0,
30065
30428
  initialLoadedPageCount: snapshot == null ? void 0 : snapshot.loadedPageCount
30066
- } : void 0)
30429
+ }, enableEventDiscoveryUrlPersistence ? {
30430
+ activeVenueTab: discoveryFilterState.venue,
30431
+ onActiveVenueTabChange: (venue) => {
30432
+ commitDiscoveryFilterState(
30433
+ __spreadProps(__spreadValues({}, discoveryFilterStateRef.current), { venue }),
30434
+ "push"
30435
+ );
30436
+ },
30437
+ selectedSort: discoveryFilterState.sort,
30438
+ onSelectedSortChange: (sort) => {
30439
+ commitDiscoveryFilterState(
30440
+ __spreadProps(__spreadValues({}, discoveryFilterStateRef.current), { sort }),
30441
+ "push"
30442
+ );
30443
+ },
30444
+ categoryPath: discoveryFilterState.subcategoryPath,
30445
+ onCategoryPathChange: (subcategoryPath, options) => {
30446
+ commitDiscoveryFilterState(
30447
+ __spreadProps(__spreadValues({}, discoveryFilterStateRef.current), { subcategoryPath }),
30448
+ options.history
30449
+ );
30450
+ }
30451
+ } : void 0) : void 0)
30067
30452
  )
30068
30453
  },
30069
30454
  `${(_a2 = eventSectionItem.id) != null ? _a2 : eventSectionItem.title}-${sectionIndex}`
@@ -30423,7 +30808,7 @@ var import_hooks77 = require("@agg-build/hooks");
30423
30808
  var import_sdk27 = require("@agg-build/sdk");
30424
30809
  var Dialog8 = __toESM(require("@radix-ui/react-dialog"));
30425
30810
  var import_react49 = require("react");
30426
- var import_zod2 = require("zod");
30811
+ var import_zod3 = require("zod");
30427
30812
  var import_jsx_runtime179 = require("react/jsx-runtime");
30428
30813
  var USDC_DECIMALS = 6;
30429
30814
  var EDITABLE_AMOUNT_PATTERN = /^\d*(?:\.\d{0,6})?$/;
@@ -30448,7 +30833,7 @@ var VENUE_LABELS = {
30448
30833
  [import_sdk27.Venue.hyperliquid]: "Hyperliquid",
30449
30834
  [import_sdk27.Venue.novig]: "Novig"
30450
30835
  };
30451
- var amountSchema = import_zod2.z.string().min(1).regex(FINAL_AMOUNT_PATTERN);
30836
+ var amountSchema = import_zod3.z.string().min(1).regex(FINAL_AMOUNT_PATTERN);
30452
30837
  var decimalToRaw = (value, decimals = USDC_DECIMALS) => {
30453
30838
  const parsed = amountSchema.safeParse(value.trim());
30454
30839
  if (!parsed.success) return null;