@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.mjs CHANGED
@@ -11,17 +11,17 @@ import {
11
11
  formatRecurringCountdown,
12
12
  formatShareAmount,
13
13
  useHomePageModals
14
- } from "./chunk-WW5QKNIM.mjs";
15
- import "./chunk-V5CRUO6S.mjs";
14
+ } from "./chunk-3UBMK2YH.mjs";
15
+ import "./chunk-C4GFVJ62.mjs";
16
16
  import {
17
17
  DEPOSIT_MODAL_OPEN_EVENT,
18
18
  WITHDRAW_MODAL_OPEN_EVENT,
19
19
  requestAggDepositModalOpen,
20
20
  requestAggWithdrawModalOpen
21
- } from "./chunk-64BBTXFE.mjs";
22
- import "./chunk-6STRIKUA.mjs";
23
- import "./chunk-734VTGCV.mjs";
24
- import "./chunk-N7UPPT5J.mjs";
21
+ } from "./chunk-KDBKKJ7W.mjs";
22
+ import "./chunk-WYCSTAN7.mjs";
23
+ import "./chunk-XN2NB2NP.mjs";
24
+ import "./chunk-RDBMHBR2.mjs";
25
25
  export {
26
26
  DEPOSIT_MODAL_OPEN_EVENT,
27
27
  EventMarketPage,
@@ -100,7 +100,7 @@ import {
100
100
  useOptionalToast,
101
101
  useToast,
102
102
  venueLogoNames
103
- } from "./chunk-N7UPPT5J.mjs";
103
+ } from "./chunk-RDBMHBR2.mjs";
104
104
  export {
105
105
  ActivityChartIcon,
106
106
  AggErrorBoundary,
package/dist/trading.js CHANGED
@@ -8444,6 +8444,37 @@ var findMatchingVenueOutcome = (market, selectedOutcome) => {
8444
8444
  return normalizedLabel !== "" && selectedNames.has(normalizedLabel);
8445
8445
  })) != null ? _b : null;
8446
8446
  };
8447
+ var resolveSellableSharesByVenue = ({
8448
+ positions,
8449
+ market,
8450
+ selectedOutcome
8451
+ }) => {
8452
+ var _a, _b, _c, _d, _e, _f, _g;
8453
+ const sharesByVenue = /* @__PURE__ */ new Map();
8454
+ if (!market || !selectedOutcome) return sharesByVenue;
8455
+ const normalizedSelectedOutcomeLabel = normalizeOutcomeName(selectedOutcome.label);
8456
+ const selectedMarketIdSet = new Set(
8457
+ [
8458
+ market.id,
8459
+ (_a = market.marketId) != null ? _a : void 0,
8460
+ (_b = market.externalIdentifier) != null ? _b : void 0,
8461
+ ...((_c = market.matchedVenueMarkets) != null ? _c : []).map((matched) => matched.id)
8462
+ ].filter((value) => Boolean(value))
8463
+ );
8464
+ for (const group of positions) {
8465
+ for (const outcome of (_e = (_d = group.venueMarket) == null ? void 0 : _d.venueMarketOutcomes) != null ? _e : []) {
8466
+ if (normalizeOutcomeName(outcome.label) !== normalizedSelectedOutcomeLabel) continue;
8467
+ for (const breakdown of (_f = outcome.venueBreakdown) != null ? _f : []) {
8468
+ const matchesMarketId = selectedMarketIdSet.size === 0 || selectedMarketIdSet.has(group.targetMarketId) || selectedMarketIdSet.has(breakdown.venueMarketId);
8469
+ if (!matchesMarketId) continue;
8470
+ const size = Number.isFinite(breakdown.size) ? breakdown.size : 0;
8471
+ if (size <= 0) continue;
8472
+ sharesByVenue.set(breakdown.venue, ((_g = sharesByVenue.get(breakdown.venue)) != null ? _g : 0) + size);
8473
+ }
8474
+ }
8475
+ }
8476
+ return sharesByVenue;
8477
+ };
8447
8478
  var buildLimitOrderVenueOptions = ({
8448
8479
  currentPrices,
8449
8480
  livePrices,
@@ -8528,7 +8559,7 @@ var getSmartRouteTotalFees = (feeBreakdown) => {
8528
8559
  if (!feeBreakdown) return null;
8529
8560
  const feeParts = [feeBreakdown.venueFees, feeBreakdown.bridgeFees, feeBreakdown.executionGas];
8530
8561
  if (!feeParts.every(Number.isFinite)) return null;
8531
- return feeParts.reduce((total, fee) => total + fee, 0);
8562
+ return feeParts.reduce((total, fee) => total + Math.round(fee * 100) / 100, 0);
8532
8563
  };
8533
8564
  var getPlaceOrderContainerClassName = () => {
8534
8565
  return PLACE_ORDER_CONTAINER_CLASS_NAME;
@@ -8790,7 +8821,7 @@ var buildLiveRouteCards = ({
8790
8821
  // balance condition, and `handleExecuteQuote` rejects an empty quoteId.
8791
8822
  sq.venue !== primaryWinnerVenue
8792
8823
  ).map((sq) => {
8793
- var _a2;
8824
+ var _a2, _b2;
8794
8825
  const parsedVenue = parseVenue(sq.venue);
8795
8826
  const venue = parsedVenue.success ? parsedVenue.data : void 0;
8796
8827
  if (geoBlockedVenues.has(sq.venue)) {
@@ -8823,7 +8854,12 @@ var buildLiveRouteCards = ({
8823
8854
  estimatedProfit: sq.estimatedProfit,
8824
8855
  returnPct: sq.returnPct,
8825
8856
  // venueSoloQuotes stripped on solo card's quoteData (only the primary needs them)
8826
- venueSoloQuotes: void 0
8857
+ venueSoloQuotes: void 0,
8858
+ // This solo's OWN fee breakdown. Without it the spread above leaves the
8859
+ // primary route's breakdown in place, so selecting a bridge-free venue
8860
+ // still showed the primary's bridging charge. Falls back to the
8861
+ // primary only when the router omitted one (non-"ok" solos).
8862
+ feeBreakdown: (_b2 = sq.feeBreakdown) != null ? _b2 : quoteData.feeBreakdown
8827
8863
  }), sq.quoteId ? { status: "ok", error: void 0 } : null);
8828
8864
  return {
8829
8865
  id: `live-solo-${sq.venue}`,
@@ -11701,6 +11737,14 @@ var PlaceOrder = ({
11701
11737
  enabled: Boolean(isAuthenticated && isSell),
11702
11738
  mode: isPaperMode ? "paper" : void 0
11703
11739
  });
11740
+ const sellableSharesByVenue = (0, import_react15.useMemo)(
11741
+ () => isSell ? resolveSellableSharesByVenue({
11742
+ positions: executionPositions,
11743
+ market: scopedSelectedMarket,
11744
+ selectedOutcome: scopedSelectedOutcome
11745
+ }) : /* @__PURE__ */ new Map(),
11746
+ [executionPositions, isSell, scopedSelectedMarket, scopedSelectedOutcome]
11747
+ );
11704
11748
  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
11705
11749
  // from the user's position for THIS outcome AND the debounced value has
11706
11750
  // caught up to it. The amount input is shared with the buy tab, so right
@@ -11751,13 +11795,26 @@ var PlaceOrder = ({
11751
11795
  }, [limitVenueQuotes.quotes]);
11752
11796
  const availableLimitVenueOptions = (0, import_react15.useMemo)(() => {
11753
11797
  return visibleLimitVenueOptions.filter((option) => {
11754
- return !geoBlockedLimitVenues.has(option.venue) && (0, import_hooks38.getVenueAvailabilityState)({
11798
+ var _a2;
11799
+ return !geoBlockedLimitVenues.has(option.venue) && // A limit SELL rests against shares held at that specific venue, so a
11800
+ // venue the user has no position on is a guaranteed 409 from the
11801
+ // server's reservation check — and the automatic pick, which sorts on
11802
+ // price alone, would happily choose one. Only narrow once we know
11803
+ // where the shares are; an empty map means positions haven't resolved.
11804
+ (!isSell || sellableSharesByVenue.size === 0 || ((_a2 = sellableSharesByVenue.get(option.venue)) != null ? _a2 : 0) > 0) && (0, import_hooks38.getVenueAvailabilityState)({
11755
11805
  venueId: option.venue,
11756
11806
  disabledVenues,
11757
11807
  isConfigLoading: isAppConfigLoading
11758
11808
  }) === "available";
11759
11809
  });
11760
- }, [disabledVenues, geoBlockedLimitVenues, isAppConfigLoading, visibleLimitVenueOptions]);
11810
+ }, [
11811
+ disabledVenues,
11812
+ geoBlockedLimitVenues,
11813
+ isAppConfigLoading,
11814
+ isSell,
11815
+ sellableSharesByVenue,
11816
+ visibleLimitVenueOptions
11817
+ ]);
11761
11818
  const automaticLimitVenueOption = (0, import_react15.useMemo)(
11762
11819
  () => resolveAutomaticLimitOrderVenueOption(availableLimitVenueOptions, internalTab),
11763
11820
  [availableLimitVenueOptions, internalTab]
@@ -11859,39 +11916,15 @@ var PlaceOrder = ({
11859
11916
  refreshContext: smartRouteRefreshContext
11860
11917
  });
11861
11918
  const currentSellableShares = (0, import_react15.useMemo)(() => {
11862
- var _a2, _b2, _c2, _d2, _e2, _f2, _g2;
11919
+ var _a2, _b2;
11863
11920
  const sharesFromQuote = (_b2 = (_a2 = smartRoute.data) == null ? void 0 : _a2.positionAvailability) == null ? void 0 : _b2.totalSellableShares;
11864
11921
  if (typeof sharesFromQuote === "number" && Number.isFinite(sharesFromQuote)) {
11865
11922
  return Math.max(0, sharesFromQuote);
11866
11923
  }
11867
- if (!isSell || !scopedSelectedOutcome || !scopedSelectedMarket) return 0;
11868
- const normalizedSelectedOutcomeLabel = scopedSelectedOutcome.label.trim().toLowerCase();
11869
- const selectedMarketIds = [
11870
- scopedSelectedMarket.id,
11871
- (_c2 = scopedSelectedMarket.marketId) != null ? _c2 : void 0,
11872
- (_d2 = scopedSelectedMarket.externalIdentifier) != null ? _d2 : void 0
11873
- ].filter((value) => Boolean(value));
11874
- const selectedMarketIdSet = new Set(selectedMarketIds);
11875
11924
  let resolvedShares = 0;
11876
- for (const group of executionPositions) {
11877
- const groupOutcomes = (_f2 = (_e2 = group.venueMarket) == null ? void 0 : _e2.venueMarketOutcomes) != null ? _f2 : [];
11878
- for (const outcome of groupOutcomes) {
11879
- if (outcome.label.trim().toLowerCase() !== normalizedSelectedOutcomeLabel) continue;
11880
- for (const breakdown of (_g2 = outcome.venueBreakdown) != null ? _g2 : []) {
11881
- const matchesMarketId = selectedMarketIdSet.size === 0 || selectedMarketIdSet.has(group.targetMarketId) || selectedMarketIdSet.has(breakdown.venueMarketId);
11882
- if (!matchesMarketId) continue;
11883
- resolvedShares += Number.isFinite(breakdown.size) ? breakdown.size : 0;
11884
- }
11885
- }
11886
- }
11925
+ for (const size of sellableSharesByVenue.values()) resolvedShares += size;
11887
11926
  return Math.max(0, resolvedShares);
11888
- }, [
11889
- executionPositions,
11890
- isSell,
11891
- scopedSelectedMarket,
11892
- scopedSelectedOutcome,
11893
- (_q = (_p = smartRoute.data) == null ? void 0 : _p.positionAvailability) == null ? void 0 : _q.totalSellableShares
11894
- ]);
11927
+ }, [sellableSharesByVenue, (_q = (_p = smartRoute.data) == null ? void 0 : _p.positionAvailability) == null ? void 0 : _q.totalSellableShares]);
11895
11928
  const maxSellableShares = (0, import_react15.useMemo)(
11896
11929
  () => floorToDecimals(currentSellableShares, SELL_SHARE_INPUT_DECIMALS),
11897
11930
  [currentSellableShares]
package/dist/trading.mjs CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  parseVenue,
13
13
  useClaimWinnings,
14
14
  useResolvedMarketClaim
15
- } from "./chunk-64BBTXFE.mjs";
15
+ } from "./chunk-KDBKKJ7W.mjs";
16
16
  import {
17
17
  SETTLEMENT_SECTION_ID,
18
18
  Settlement,
@@ -30,9 +30,9 @@ import {
30
30
  prepareSettlementDifferences,
31
31
  resolveDifferenceIconClassName,
32
32
  useEventTradingContext
33
- } from "./chunk-6STRIKUA.mjs";
34
- import "./chunk-734VTGCV.mjs";
35
- import "./chunk-N7UPPT5J.mjs";
33
+ } from "./chunk-WYCSTAN7.mjs";
34
+ import "./chunk-XN2NB2NP.mjs";
35
+ import "./chunk-RDBMHBR2.mjs";
36
36
  export {
37
37
  FundKalshiModal,
38
38
  PlaceOrder,
@@ -1,4 +1,6 @@
1
1
  import type { AggUiLabels } from "@agg-build/hooks";
2
- import type { EventListTab } from "./event-list.types";
2
+ import type { EventListSortValue, EventListTab } from "./event-list.types";
3
3
  export declare const DEFAULT_EVENTS_LIMIT = 50;
4
+ export declare const DEFAULT_EVENT_LIST_SORT: EventListSortValue;
5
+ export declare const EVENT_LIST_SORT_VALUES: readonly ["volume24hr", "topArbitrage", "volume", "endDate"];
4
6
  export declare const getDefaultEventListTabs: (labels: AggUiLabels) => EventListTab[];
@@ -1,4 +1,6 @@
1
1
  import type { AggUiLabels } from "@agg-build/hooks";
2
- import type { EventListTab } from "./event-list.types";
2
+ import type { EventListSortValue, EventListTab } from "./event-list.types";
3
3
  export declare const DEFAULT_EVENTS_LIMIT = 50;
4
+ export declare const DEFAULT_EVENT_LIST_SORT: EventListSortValue;
5
+ export declare const EVENT_LIST_SORT_VALUES: readonly ["volume24hr", "topArbitrage", "volume", "endDate"];
4
6
  export declare const getDefaultEventListTabs: (labels: AggUiLabels) => EventListTab[];
@@ -4,7 +4,12 @@ import type { MutableRefObject } from "react";
4
4
  import type { IconName } from "../../primitives/icon";
5
5
  import type { VenueLogoName } from "../../primitives/venue-logo";
6
6
  import type { VenueEventWithMarkets, VenueMarket, VenueMarketOutcome } from "../item";
7
+ import type { SubcategoryPathEntry } from "./event-list.utils";
7
8
  export type EventListTabValue = "matched" | "all" | `${Venue}` | (string & {});
9
+ export type EventListSortValue = "volume24hr" | "topArbitrage" | "volume" | "endDate";
10
+ export type EventListFilterChangeOptions = {
11
+ history: "push" | "replace";
12
+ };
8
13
  /** Exposes EventList internal state for snapshot capture by parent components. */
9
14
  export type EventListStateRef = {
10
15
  venueTab: EventListTabValue;
@@ -43,6 +48,18 @@ export type EventListProps = {
43
48
  getEventHref?: (event: VenueEventWithMarkets) => string;
44
49
  /** Venue tab value to restore on mount (from navigation snapshot). */
45
50
  initialVenueTab?: EventListTabValue;
51
+ /** Controlled venue tab value. Omit to retain EventList's local-state behavior. */
52
+ activeVenueTab?: EventListTabValue;
53
+ /** Called when the controlled venue tab changes. */
54
+ onActiveVenueTabChange?: (value: EventListTabValue, options: EventListFilterChangeOptions) => void;
55
+ /** Controlled sort value. Omit to retain EventList's local-state behavior. */
56
+ selectedSort?: EventListSortValue;
57
+ /** Called when the controlled sort changes. */
58
+ onSelectedSortChange?: (value: EventListSortValue, options: EventListFilterChangeOptions) => void;
59
+ /** Controlled ordered subcategory path. Omit to retain EventList's local-state behavior. */
60
+ categoryPath?: SubcategoryPathEntry[];
61
+ /** Called when the controlled subcategory path changes. */
62
+ onCategoryPathChange?: (value: SubcategoryPathEntry[], options: EventListFilterChangeOptions) => void;
46
63
  /** Number of infinite query pages to eagerly prefetch on mount (from navigation snapshot). */
47
64
  initialLoadedPageCount?: number;
48
65
  /** Ref that EventList writes its internal state to, so parents can read it for snapshot capture. */
@@ -4,7 +4,12 @@ import type { MutableRefObject } from "react";
4
4
  import type { IconName } from "../../primitives/icon";
5
5
  import type { VenueLogoName } from "../../primitives/venue-logo";
6
6
  import type { VenueEventWithMarkets, VenueMarket, VenueMarketOutcome } from "../item";
7
+ import type { SubcategoryPathEntry } from "./event-list.utils";
7
8
  export type EventListTabValue = "matched" | "all" | `${Venue}` | (string & {});
9
+ export type EventListSortValue = "volume24hr" | "topArbitrage" | "volume" | "endDate";
10
+ export type EventListFilterChangeOptions = {
11
+ history: "push" | "replace";
12
+ };
8
13
  /** Exposes EventList internal state for snapshot capture by parent components. */
9
14
  export type EventListStateRef = {
10
15
  venueTab: EventListTabValue;
@@ -43,6 +48,18 @@ export type EventListProps = {
43
48
  getEventHref?: (event: VenueEventWithMarkets) => string;
44
49
  /** Venue tab value to restore on mount (from navigation snapshot). */
45
50
  initialVenueTab?: EventListTabValue;
51
+ /** Controlled venue tab value. Omit to retain EventList's local-state behavior. */
52
+ activeVenueTab?: EventListTabValue;
53
+ /** Called when the controlled venue tab changes. */
54
+ onActiveVenueTabChange?: (value: EventListTabValue, options: EventListFilterChangeOptions) => void;
55
+ /** Controlled sort value. Omit to retain EventList's local-state behavior. */
56
+ selectedSort?: EventListSortValue;
57
+ /** Called when the controlled sort changes. */
58
+ onSelectedSortChange?: (value: EventListSortValue, options: EventListFilterChangeOptions) => void;
59
+ /** Controlled ordered subcategory path. Omit to retain EventList's local-state behavior. */
60
+ categoryPath?: SubcategoryPathEntry[];
61
+ /** Called when the controlled subcategory path changes. */
62
+ onCategoryPathChange?: (value: SubcategoryPathEntry[], options: EventListFilterChangeOptions) => void;
46
63
  /** Number of infinite query pages to eagerly prefetch on mount (from navigation snapshot). */
47
64
  initialLoadedPageCount?: number;
48
65
  /** Ref that EventList writes its internal state to, so parents can read it for snapshot capture. */
@@ -31,4 +31,8 @@ export declare const sortCategoriesForNavigation: <TCategory extends CategoryNav
31
31
  * - With an empty path, use the provided fallback category ids.
32
32
  */
33
33
  export declare const resolveCategoryIdsFromPath: (path: readonly SubcategoryPathEntry[], fallbackCategoryIds: string[] | undefined) => string[] | undefined;
34
+ export declare const validateSubcategoryPath: <TCategory extends {
35
+ id: string;
36
+ parentId: string | null;
37
+ }>(requestedPath: readonly string[], rootCategoryId: string | null, childrenByParentId: ReadonlyMap<string, readonly TCategory[]>) => string[];
34
38
  export declare const resolveTabVenus: (tab: EventListTab | undefined, visibleVenues?: readonly string[]) => UseVenueEventsOptions["venues"] | undefined;
@@ -31,4 +31,8 @@ export declare const sortCategoriesForNavigation: <TCategory extends CategoryNav
31
31
  * - With an empty path, use the provided fallback category ids.
32
32
  */
33
33
  export declare const resolveCategoryIdsFromPath: (path: readonly SubcategoryPathEntry[], fallbackCategoryIds: string[] | undefined) => string[] | undefined;
34
+ export declare const validateSubcategoryPath: <TCategory extends {
35
+ id: string;
36
+ parentId: string | null;
37
+ }>(requestedPath: readonly string[], rootCategoryId: string | null, childrenByParentId: ReadonlyMap<string, readonly TCategory[]>) => string[];
34
38
  export declare const resolveTabVenus: (tab: EventListTab | undefined, visibleVenues?: readonly string[]) => UseVenueEventsOptions["venues"] | undefined;
@@ -1,7 +1,7 @@
1
1
  import type { EventListProps } from "./event-list.types";
2
2
  export type { CategorySidebarLabels, CategorySidebarProps } from "./category-sidebar";
3
- export type { EventListProps, EventListStateRef } from "./event-list.types";
3
+ export type { EventListFilterChangeOptions, EventListProps, EventListSortValue, EventListStateRef, } from "./event-list.types";
4
4
  export declare const EventList: {
5
- ({ title, limit, maxVisibleItems, search, categoryIds, onCategoryRootChange, onEventClick, onMarketClick, getMarketHref, getEventHref, initialVenueTab, initialLoadedPageCount, stateRef, }: EventListProps): JSX.Element;
5
+ ({ title, limit, maxVisibleItems, search, categoryIds, onCategoryRootChange, onEventClick, onMarketClick, getMarketHref, getEventHref, initialVenueTab, activeVenueTab: controlledActiveVenueTab, onActiveVenueTabChange, selectedSort: controlledSelectedSort, onSelectedSortChange, categoryPath: controlledCategoryPath, onCategoryPathChange, initialLoadedPageCount, stateRef, }: EventListProps): JSX.Element;
6
6
  displayName: string;
7
7
  };
@@ -1,7 +1,7 @@
1
1
  import type { EventListProps } from "./event-list.types";
2
2
  export type { CategorySidebarLabels, CategorySidebarProps } from "./category-sidebar";
3
- export type { EventListProps, EventListStateRef } from "./event-list.types";
3
+ export type { EventListFilterChangeOptions, EventListProps, EventListSortValue, EventListStateRef, } from "./event-list.types";
4
4
  export declare const EventList: {
5
- ({ title, limit, maxVisibleItems, search, categoryIds, onCategoryRootChange, onEventClick, onMarketClick, getMarketHref, getEventHref, initialVenueTab, initialLoadedPageCount, stateRef, }: EventListProps): JSX.Element;
5
+ ({ title, limit, maxVisibleItems, search, categoryIds, onCategoryRootChange, onEventClick, onMarketClick, getMarketHref, getEventHref, initialVenueTab, activeVenueTab: controlledActiveVenueTab, onActiveVenueTabChange, selectedSort: controlledSelectedSort, onSelectedSortChange, categoryPath: controlledCategoryPath, onCategoryPathChange, initialLoadedPageCount, stateRef, }: EventListProps): JSX.Element;
6
6
  displayName: string;
7
7
  };
@@ -0,0 +1,35 @@
1
+ import { DEFAULT_EVENT_LIST_SORT, EVENT_LIST_SORT_VALUES } from "../../events/list/event-list.constants";
2
+ import type { EventListSortValue } from "../../events/list/event-list.types";
3
+ export { DEFAULT_EVENT_LIST_SORT, EVENT_LIST_SORT_VALUES };
4
+ export type { EventListSortValue };
5
+ export type EventDiscoveryUrlState = {
6
+ category: string;
7
+ subcategoryPath: string[];
8
+ venue: string;
9
+ sort: EventListSortValue;
10
+ };
11
+ type ParsedEventDiscoveryUrlState = {
12
+ category?: string;
13
+ subcategoryPath: string[];
14
+ venue?: string;
15
+ sort?: EventListSortValue;
16
+ categoryIsInvalid: boolean;
17
+ shouldCanonicalize: boolean;
18
+ };
19
+ export declare const readEventDiscoveryUrlState: (searchParams: URLSearchParams) => ParsedEventDiscoveryUrlState;
20
+ export declare const resolveEventDiscoveryUrlState: ({ parsedState, categoryValues, venueValues, defaultCategory, defaultVenue, }: {
21
+ parsedState: ParsedEventDiscoveryUrlState;
22
+ categoryValues: readonly string[];
23
+ venueValues: readonly string[];
24
+ defaultCategory: string;
25
+ defaultVenue: string;
26
+ }) => {
27
+ state: EventDiscoveryUrlState;
28
+ shouldCanonicalize: boolean;
29
+ };
30
+ export declare const buildEventDiscoveryUrl: ({ currentUrl, state, defaultCategory, defaultVenue, }: {
31
+ currentUrl: URL;
32
+ state: EventDiscoveryUrlState;
33
+ defaultCategory: string;
34
+ defaultVenue: string;
35
+ }) => string;
@@ -0,0 +1,35 @@
1
+ import { DEFAULT_EVENT_LIST_SORT, EVENT_LIST_SORT_VALUES } from "../../events/list/event-list.constants";
2
+ import type { EventListSortValue } from "../../events/list/event-list.types";
3
+ export { DEFAULT_EVENT_LIST_SORT, EVENT_LIST_SORT_VALUES };
4
+ export type { EventListSortValue };
5
+ export type EventDiscoveryUrlState = {
6
+ category: string;
7
+ subcategoryPath: string[];
8
+ venue: string;
9
+ sort: EventListSortValue;
10
+ };
11
+ type ParsedEventDiscoveryUrlState = {
12
+ category?: string;
13
+ subcategoryPath: string[];
14
+ venue?: string;
15
+ sort?: EventListSortValue;
16
+ categoryIsInvalid: boolean;
17
+ shouldCanonicalize: boolean;
18
+ };
19
+ export declare const readEventDiscoveryUrlState: (searchParams: URLSearchParams) => ParsedEventDiscoveryUrlState;
20
+ export declare const resolveEventDiscoveryUrlState: ({ parsedState, categoryValues, venueValues, defaultCategory, defaultVenue, }: {
21
+ parsedState: ParsedEventDiscoveryUrlState;
22
+ categoryValues: readonly string[];
23
+ venueValues: readonly string[];
24
+ defaultCategory: string;
25
+ defaultVenue: string;
26
+ }) => {
27
+ state: EventDiscoveryUrlState;
28
+ shouldCanonicalize: boolean;
29
+ };
30
+ export declare const buildEventDiscoveryUrl: ({ currentUrl, state, defaultCategory, defaultVenue, }: {
31
+ currentUrl: URL;
32
+ state: EventDiscoveryUrlState;
33
+ defaultCategory: string;
34
+ defaultVenue: string;
35
+ }) => string;
@@ -10,6 +10,32 @@ export declare const isPlaceOrderAveragePriceWorse: ({ averageExecutionPrice, di
10
10
  }) => boolean;
11
11
  export declare const floorToDecimals: (value: number, decimals: number) => number;
12
12
  export declare const formatFlooredShareAmount: (value: number, decimals: number) => string;
13
+ /** Minimal structural view of `useExecutionPositions` rows this module reads. */
14
+ export interface SellablePositionGroup {
15
+ targetMarketId: string;
16
+ venueMarket?: {
17
+ venueMarketOutcomes?: {
18
+ label: string;
19
+ venueBreakdown?: {
20
+ venue: string;
21
+ venueMarketId: string;
22
+ size: number;
23
+ }[];
24
+ }[];
25
+ };
26
+ }
27
+ /**
28
+ * Gross held shares for `selectedOutcome`, keyed by the venue holding them.
29
+ *
30
+ * Positions sit on ONE venue market of a matched cluster, so the accepted id
31
+ * set spans `matchedVenueMarkets` as well — scoping it to the selected market
32
+ * alone reads a cluster position held on another venue as zero.
33
+ */
34
+ export declare const resolveSellableSharesByVenue: ({ positions, market, selectedOutcome, }: {
35
+ positions: readonly SellablePositionGroup[];
36
+ market: VenueMarket | null | undefined;
37
+ selectedOutcome: VenueMarket["venueMarketOutcomes"][number] | null | undefined;
38
+ }) => Map<string, number>;
13
39
  export declare const buildLimitOrderVenueOptions: ({ currentPrices, livePrices, market, selectedOutcomeId, }: {
14
40
  currentPrices: ReadonlyMap<string, number>;
15
41
  livePrices?: ReadonlyMap<string, number>;
@@ -10,6 +10,32 @@ export declare const isPlaceOrderAveragePriceWorse: ({ averageExecutionPrice, di
10
10
  }) => boolean;
11
11
  export declare const floorToDecimals: (value: number, decimals: number) => number;
12
12
  export declare const formatFlooredShareAmount: (value: number, decimals: number) => string;
13
+ /** Minimal structural view of `useExecutionPositions` rows this module reads. */
14
+ export interface SellablePositionGroup {
15
+ targetMarketId: string;
16
+ venueMarket?: {
17
+ venueMarketOutcomes?: {
18
+ label: string;
19
+ venueBreakdown?: {
20
+ venue: string;
21
+ venueMarketId: string;
22
+ size: number;
23
+ }[];
24
+ }[];
25
+ };
26
+ }
27
+ /**
28
+ * Gross held shares for `selectedOutcome`, keyed by the venue holding them.
29
+ *
30
+ * Positions sit on ONE venue market of a matched cluster, so the accepted id
31
+ * set spans `matchedVenueMarkets` as well — scoping it to the selected market
32
+ * alone reads a cluster position held on another venue as zero.
33
+ */
34
+ export declare const resolveSellableSharesByVenue: ({ positions, market, selectedOutcome, }: {
35
+ positions: readonly SellablePositionGroup[];
36
+ market: VenueMarket | null | undefined;
37
+ selectedOutcome: VenueMarket["venueMarketOutcomes"][number] | null | undefined;
38
+ }) => Map<string, number>;
13
39
  export declare const buildLimitOrderVenueOptions: ({ currentPrices, livePrices, market, selectedOutcomeId, }: {
14
40
  currentPrices: ReadonlyMap<string, number>;
15
41
  livePrices?: ReadonlyMap<string, number>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agg-build/ui",
3
- "version": "4.4.0",
3
+ "version": "4.7.2",
4
4
  "description": "Pre-built React component library for the AGG prediction market aggregator. Tailwind-based, themeable, with primitives, event surfaces, trading flows, full pages, and modals.",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",
@@ -100,8 +100,8 @@
100
100
  "liveline": "^0.0.7",
101
101
  "react": "^18.0.0 || ^19.0.0",
102
102
  "react-dom": "^18.0.0 || ^19.0.0",
103
- "@agg-build/hooks": "^4.4.0",
104
- "@agg-build/sdk": "^4.3.0"
103
+ "@agg-build/hooks": "^4.7.0",
104
+ "@agg-build/sdk": "^4.7.0"
105
105
  },
106
106
  "dependencies": {
107
107
  "@number-flow/react": "^0.6.0",