@agg-build/ui 2.1.1 → 2.1.3

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 (74) hide show
  1. package/dist/{chunk-XHDGSRG7.mjs → chunk-BW7S2YR3.mjs} +1139 -308
  2. package/dist/{chunk-TERG43WW.mjs → chunk-R2YNZJZ3.mjs} +69 -27
  3. package/dist/{chunk-RPXRTXCY.mjs → chunk-T4YZGAYS.mjs} +22 -1
  4. package/dist/{chunk-IQT4I5B4.mjs → chunk-TAGPAADA.mjs} +2108 -767
  5. package/dist/{chunk-NK57KMYN.mjs → chunk-TBZWRUFB.mjs} +752 -589
  6. package/dist/{chunk-YJO6LMRT.mjs → chunk-VP76G6PN.mjs} +87 -25
  7. package/dist/{chunk-WU2C3C6K.mjs → chunk-XHE2VO3S.mjs} +4 -21
  8. package/dist/events.js +1014 -760
  9. package/dist/events.mjs +5 -3
  10. package/dist/index.js +9937 -7880
  11. package/dist/index.mjs +117 -456
  12. package/dist/modals.js +1 -1
  13. package/dist/modals.mjs +3 -3
  14. package/dist/pages.js +8513 -6380
  15. package/dist/pages.mjs +6 -6
  16. package/dist/primitives.js +85 -25
  17. package/dist/primitives.mjs +1 -1
  18. package/dist/styles.css +1 -1
  19. package/dist/tailwind.css +1 -1
  20. package/dist/trading.js +979 -402
  21. package/dist/trading.mjs +10 -6
  22. package/dist/types/events/item/event-list-item.utils.d.mts +1 -25
  23. package/dist/types/events/item/event-list-item.utils.d.ts +1 -25
  24. package/dist/types/events/item-details/index.d.mts +2 -1
  25. package/dist/types/events/item-details/index.d.ts +2 -1
  26. package/dist/types/events/market-details/market-details-graph-panel.d.mts +39 -0
  27. package/dist/types/events/market-details/market-details-graph-panel.d.ts +39 -0
  28. package/dist/types/events/market-details/market-details-outcome-button.d.mts +2 -1
  29. package/dist/types/events/market-details/market-details-outcome-button.d.ts +2 -1
  30. package/dist/types/events/market-details/market-details.types.d.mts +31 -0
  31. package/dist/types/events/market-details/market-details.types.d.ts +31 -0
  32. package/dist/types/events/market-details/market-details.utils.d.mts +3 -16
  33. package/dist/types/events/market-details/market-details.utils.d.ts +3 -16
  34. package/dist/types/events/shared/format-event-title.d.mts +24 -0
  35. package/dist/types/events/shared/format-event-title.d.ts +24 -0
  36. package/dist/types/events/shared/format-sports-event-time.d.mts +2 -0
  37. package/dist/types/events/shared/format-sports-event-time.d.ts +2 -0
  38. package/dist/types/events/shared/select-best-outcome.d.mts +88 -0
  39. package/dist/types/events/shared/select-best-outcome.d.ts +88 -0
  40. package/dist/types/notifications/agg-notification-events-provider.d.mts +10 -1
  41. package/dist/types/notifications/agg-notification-events-provider.d.ts +10 -1
  42. package/dist/types/pages/event-market/event-market.shared.d.mts +30 -0
  43. package/dist/types/pages/event-market/event-market.shared.d.ts +30 -0
  44. package/dist/types/pages/event-market/event-market.types.d.mts +7 -0
  45. package/dist/types/pages/event-market/event-market.types.d.ts +7 -0
  46. package/dist/types/pages/event-market/sports-event-market-page.d.mts +8 -0
  47. package/dist/types/pages/event-market/sports-event-market-page.d.ts +8 -0
  48. package/dist/types/pages/event-market/sports-event-market.fixtures.d.mts +13 -0
  49. package/dist/types/pages/event-market/sports-event-market.fixtures.d.ts +13 -0
  50. package/dist/types/pages/event-market/sports-event-market.utils.d.mts +156 -0
  51. package/dist/types/pages/event-market/sports-event-market.utils.d.ts +156 -0
  52. package/dist/types/pages/event-market/sports-line-rail.d.mts +17 -0
  53. package/dist/types/pages/event-market/sports-line-rail.d.ts +17 -0
  54. package/dist/types/pages/event-market/sports-market-card.d.mts +22 -0
  55. package/dist/types/pages/event-market/sports-market-card.d.ts +22 -0
  56. package/dist/types/pages/event-market/sports-markets.d.mts +13 -0
  57. package/dist/types/pages/event-market/sports-markets.d.ts +13 -0
  58. package/dist/types/primitives/state-message/index.d.mts +1 -1
  59. package/dist/types/primitives/state-message/index.d.ts +1 -1
  60. package/dist/types/primitives/state-message/state-message.types.d.mts +1 -1
  61. package/dist/types/primitives/state-message/state-message.types.d.ts +1 -1
  62. package/dist/types/trading/index.d.mts +2 -0
  63. package/dist/types/trading/index.d.ts +2 -0
  64. package/dist/types/trading/place-order/index.d.mts +1 -1
  65. package/dist/types/trading/place-order/index.d.ts +1 -1
  66. package/dist/types/trading/place-order/index.place-order.types.d.mts +30 -1
  67. package/dist/types/trading/place-order/index.place-order.types.d.ts +30 -1
  68. package/dist/types/trading/settlement/settlement-text.utils.d.mts +5 -2
  69. package/dist/types/trading/settlement/settlement-text.utils.d.ts +5 -2
  70. package/dist/types/trading/use-claim-winnings.d.mts +84 -0
  71. package/dist/types/trading/use-claim-winnings.d.ts +84 -0
  72. package/dist/types/trading/use-resolved-market-claim.d.mts +26 -0
  73. package/dist/types/trading/use-resolved-market-claim.d.ts +26 -0
  74. package/package.json +3 -3
package/dist/trading.mjs CHANGED
@@ -5,8 +5,10 @@ import {
5
5
  PlaceOrderSuccessView,
6
6
  SettlementDetails,
7
7
  parseAmount,
8
- parseVenue
9
- } from "./chunk-XHDGSRG7.mjs";
8
+ parseVenue,
9
+ useClaimWinnings,
10
+ useResolvedMarketClaim
11
+ } from "./chunk-BW7S2YR3.mjs";
10
12
  import {
11
13
  SETTLEMENT_SECTION_ID,
12
14
  Settlement,
@@ -21,9 +23,9 @@ import {
21
23
  getTradingValueLabel,
22
24
  getTradingVenueLabel,
23
25
  useEventTradingContext
24
- } from "./chunk-TERG43WW.mjs";
25
- import "./chunk-RPXRTXCY.mjs";
26
- import "./chunk-YJO6LMRT.mjs";
26
+ } from "./chunk-R2YNZJZ3.mjs";
27
+ import "./chunk-T4YZGAYS.mjs";
28
+ import "./chunk-VP76G6PN.mjs";
27
29
  export {
28
30
  PlaceOrder,
29
31
  PlaceOrderFailureView,
@@ -43,5 +45,7 @@ export {
43
45
  getTradingVenueLabel,
44
46
  parseAmount,
45
47
  parseVenue,
46
- useEventTradingContext
48
+ useClaimWinnings,
49
+ useEventTradingContext,
50
+ useResolvedMarketClaim
47
51
  };
@@ -1,18 +1,5 @@
1
1
  import type { AggUiLabels, VenueMarket, VenueMarketOutcome } from "@agg-build/hooks";
2
2
  import type { EventListItemEvent, EventListItemVenueInfoMap, VenueEventWithMarkets } from "./event-list-item.types";
3
- /**
4
- * Filter a list of venue strings against a runtime-derived set of
5
- * tradeable venues. When `tradableVenues` is null (loading / unknown)
6
- * the input is returned unchanged so callers can optimistically show
7
- * all venues until the orderbook signal arrives. When `tradableVenues`
8
- * is a Set, only venues present in it are kept.
9
- *
10
- * The Set is typically produced by `useTradableVenues(venueMarkets)`
11
- * from `@agg-build/hooks`, which observes per-outcome midpoints from the
12
- * engine and treats a venue as tradeable iff at least one of its
13
- * outcomes has a non-null midpoint.
14
- */
15
- export declare const filterVenuesByTradable: <T extends string>(venues: readonly T[], tradableVenues: ReadonlySet<string> | null | undefined) => T[];
16
3
  export declare const resolveEventListItemEvent: (fetchedEvent: VenueEventWithMarkets | undefined) => EventListItemEvent | undefined;
17
4
  export declare const normalizeProbability: (value: number | null | undefined) => number | undefined;
18
5
  export declare const isYesLabel: (label: string) => boolean;
@@ -59,18 +46,7 @@ export declare const selectPrimaryVenueMarket: (venueMarkets: VenueMarket[]) =>
59
46
  export declare const resolveTileTitle: (event: VenueEventWithMarkets, primaryVenueMarket: VenueMarket | undefined, titleOverride: string | undefined) => string;
60
47
  export declare const resolveTileImage: (event: VenueEventWithMarkets, primaryVenueMarket: VenueMarket | undefined, imageOverride: string | null | undefined) => string | undefined;
61
48
  export declare const formatCountLabel: (count: number, singular: string, plural: string) => string;
62
- export declare const getVenueSummary: (venueMarkets: VenueMarket[], options?: {
63
- /**
64
- * Runtime-derived set of venues that have a live orderbook (typically
65
- * sourced from `useTradableVenues`). When provided as a Set, only
66
- * venues in the set count toward `venueCount` and `singleVenue`.
67
- * When `null` (loading) or `undefined` (caller doesn't have the
68
- * signal), no filter is applied and all venues count — callers
69
- * showing a "X venues" badge accept that the count may briefly
70
- * include non-tradeable venues until midpoints resolve.
71
- */
72
- tradableVenues?: ReadonlySet<string> | null;
73
- }) => {
49
+ export declare const getVenueSummary: (venueMarkets: VenueMarket[]) => {
74
50
  marketCount: number;
75
51
  venueCount: number;
76
52
  singleVenue: import("@agg-build/hooks").Venue | undefined;
@@ -1,18 +1,5 @@
1
1
  import type { AggUiLabels, VenueMarket, VenueMarketOutcome } from "@agg-build/hooks";
2
2
  import type { EventListItemEvent, EventListItemVenueInfoMap, VenueEventWithMarkets } from "./event-list-item.types";
3
- /**
4
- * Filter a list of venue strings against a runtime-derived set of
5
- * tradeable venues. When `tradableVenues` is null (loading / unknown)
6
- * the input is returned unchanged so callers can optimistically show
7
- * all venues until the orderbook signal arrives. When `tradableVenues`
8
- * is a Set, only venues present in it are kept.
9
- *
10
- * The Set is typically produced by `useTradableVenues(venueMarkets)`
11
- * from `@agg-build/hooks`, which observes per-outcome midpoints from the
12
- * engine and treats a venue as tradeable iff at least one of its
13
- * outcomes has a non-null midpoint.
14
- */
15
- export declare const filterVenuesByTradable: <T extends string>(venues: readonly T[], tradableVenues: ReadonlySet<string> | null | undefined) => T[];
16
3
  export declare const resolveEventListItemEvent: (fetchedEvent: VenueEventWithMarkets | undefined) => EventListItemEvent | undefined;
17
4
  export declare const normalizeProbability: (value: number | null | undefined) => number | undefined;
18
5
  export declare const isYesLabel: (label: string) => boolean;
@@ -59,18 +46,7 @@ export declare const selectPrimaryVenueMarket: (venueMarkets: VenueMarket[]) =>
59
46
  export declare const resolveTileTitle: (event: VenueEventWithMarkets, primaryVenueMarket: VenueMarket | undefined, titleOverride: string | undefined) => string;
60
47
  export declare const resolveTileImage: (event: VenueEventWithMarkets, primaryVenueMarket: VenueMarket | undefined, imageOverride: string | null | undefined) => string | undefined;
61
48
  export declare const formatCountLabel: (count: number, singular: string, plural: string) => string;
62
- export declare const getVenueSummary: (venueMarkets: VenueMarket[], options?: {
63
- /**
64
- * Runtime-derived set of venues that have a live orderbook (typically
65
- * sourced from `useTradableVenues`). When provided as a Set, only
66
- * venues in the set count toward `venueCount` and `singleVenue`.
67
- * When `null` (loading) or `undefined` (caller doesn't have the
68
- * signal), no filter is applied and all venues count — callers
69
- * showing a "X venues" badge accept that the count may briefly
70
- * include non-tradeable venues until midpoints resolve.
71
- */
72
- tradableVenues?: ReadonlySet<string> | null;
73
- }) => {
49
+ export declare const getVenueSummary: (venueMarkets: VenueMarket[]) => {
74
50
  marketCount: number;
75
51
  venueCount: number;
76
52
  singleVenue: import("@agg-build/hooks").Venue | undefined;
@@ -1,7 +1,8 @@
1
- import type { EventListItemDetailsProps } from "./event-list-item-details.types";
1
+ import type { EventListItemDetailsContentProps, EventListItemDetailsProps } from "./event-list-item-details.types";
2
2
  export type { EventListItemDetailsClassNames, EventListItemDetailsEvent, EventListItemDetailsProps, EventListItemDetailsStat, EventListItemDetailsTimeRange, EventListItemDetailsWithEventIdProps, } from "./event-list-item-details.types";
3
3
  export { SettlementSummary } from "./settlement-summary";
4
4
  export type { SettlementSummaryProps } from "./settlement-summary";
5
+ export declare const resolveEventDetailsSyncKey: (event: EventListItemDetailsContentProps["event"]) => string;
5
6
  export declare const EventListItemDetails: {
6
7
  (props: EventListItemDetailsProps): JSX.Element;
7
8
  displayName: string;
@@ -1,7 +1,8 @@
1
- import type { EventListItemDetailsProps } from "./event-list-item-details.types";
1
+ import type { EventListItemDetailsContentProps, EventListItemDetailsProps } from "./event-list-item-details.types";
2
2
  export type { EventListItemDetailsClassNames, EventListItemDetailsEvent, EventListItemDetailsProps, EventListItemDetailsStat, EventListItemDetailsTimeRange, EventListItemDetailsWithEventIdProps, } from "./event-list-item-details.types";
3
3
  export { SettlementSummary } from "./settlement-summary";
4
4
  export type { SettlementSummaryProps } from "./settlement-summary";
5
+ export declare const resolveEventDetailsSyncKey: (event: EventListItemDetailsContentProps["event"]) => string;
5
6
  export declare const EventListItemDetails: {
6
7
  (props: EventListItemDetailsProps): JSX.Element;
7
8
  displayName: string;
@@ -0,0 +1,39 @@
1
+ import type { VenueMarket } from "@agg-build/hooks";
2
+ import type { MarketDetailsHeaderOutcomeItem } from "./market-details.types";
3
+ export interface MarketDetailsGraphPanelProps {
4
+ /**
5
+ * The card's own cross-venue cluster (`model.market.venueMarkets`), NOT the
6
+ * full event market set. Scoping here keeps the chart's outcome resolution +
7
+ * WS subscription limited to this market.
8
+ */
9
+ venueMarkets: VenueMarket[];
10
+ selectedOutcomeLabel: string | null;
11
+ selectedOutcomeId: string | null;
12
+ /** Merged REST+WS live prices, used to rank/scope chart venue outcomes. */
13
+ livePrices: Map<string, number>;
14
+ /** WS-only per-outcome midpoints, used for the per-venue chart badges. */
15
+ wsLivePrices: Map<string, number>;
16
+ headerOutcomeItems: MarketDetailsHeaderOutcomeItem[];
17
+ isResolvedMarket: boolean;
18
+ isOutcomeSelectionLocked: boolean;
19
+ volume: number | null | undefined;
20
+ live?: boolean;
21
+ classNames?: {
22
+ graph?: string;
23
+ footer?: string;
24
+ };
25
+ }
26
+ /**
27
+ * Self-contained chart panel for an expanded market card.
28
+ *
29
+ * IMPORTANT: every chart data hook (`useMarketChart`, `useRollingChartWindow`)
30
+ * and all chart-local state live HERE, not in the parent `MarketDetails`. The
31
+ * parent renders this component only while the card is open AND the Graph tab
32
+ * is active, so inactive/closed cards never mount these hooks — no `/charts/bars`
33
+ * request, no chart query-cache entries, and no 1s rolling-window timer are
34
+ * created for markets the user isn't actively charting.
35
+ */
36
+ export declare const MarketDetailsGraphPanel: {
37
+ ({ venueMarkets, selectedOutcomeLabel, selectedOutcomeId, livePrices, wsLivePrices, headerOutcomeItems, isResolvedMarket, isOutcomeSelectionLocked, volume, live, classNames, }: MarketDetailsGraphPanelProps): JSX.Element;
38
+ displayName: string;
39
+ };
@@ -0,0 +1,39 @@
1
+ import type { VenueMarket } from "@agg-build/hooks";
2
+ import type { MarketDetailsHeaderOutcomeItem } from "./market-details.types";
3
+ export interface MarketDetailsGraphPanelProps {
4
+ /**
5
+ * The card's own cross-venue cluster (`model.market.venueMarkets`), NOT the
6
+ * full event market set. Scoping here keeps the chart's outcome resolution +
7
+ * WS subscription limited to this market.
8
+ */
9
+ venueMarkets: VenueMarket[];
10
+ selectedOutcomeLabel: string | null;
11
+ selectedOutcomeId: string | null;
12
+ /** Merged REST+WS live prices, used to rank/scope chart venue outcomes. */
13
+ livePrices: Map<string, number>;
14
+ /** WS-only per-outcome midpoints, used for the per-venue chart badges. */
15
+ wsLivePrices: Map<string, number>;
16
+ headerOutcomeItems: MarketDetailsHeaderOutcomeItem[];
17
+ isResolvedMarket: boolean;
18
+ isOutcomeSelectionLocked: boolean;
19
+ volume: number | null | undefined;
20
+ live?: boolean;
21
+ classNames?: {
22
+ graph?: string;
23
+ footer?: string;
24
+ };
25
+ }
26
+ /**
27
+ * Self-contained chart panel for an expanded market card.
28
+ *
29
+ * IMPORTANT: every chart data hook (`useMarketChart`, `useRollingChartWindow`)
30
+ * and all chart-local state live HERE, not in the parent `MarketDetails`. The
31
+ * parent renders this component only while the card is open AND the Graph tab
32
+ * is active, so inactive/closed cards never mount these hooks — no `/charts/bars`
33
+ * request, no chart query-cache entries, and no 1s rolling-window timer are
34
+ * created for markets the user isn't actively charting.
35
+ */
36
+ export declare const MarketDetailsGraphPanel: {
37
+ ({ venueMarkets, selectedOutcomeLabel, selectedOutcomeId, livePrices, wsLivePrices, headerOutcomeItems, isResolvedMarket, isOutcomeSelectionLocked, volume, live, classNames, }: MarketDetailsGraphPanelProps): JSX.Element;
38
+ displayName: string;
39
+ };
@@ -2,12 +2,13 @@ import type { MarketDetailsHeaderOutcomeItem } from "./market-details.types";
2
2
  type MarketDetailsOutcomeButtonProps = {
3
3
  ariaControls?: string;
4
4
  enableAnimations: boolean;
5
+ enforceFixedWidth?: boolean;
5
6
  isSelected: boolean;
6
7
  item: MarketDetailsHeaderOutcomeItem;
7
8
  onSelect: (label: string) => void;
8
9
  };
9
10
  export declare const MarketDetailsOutcomeButton: {
10
- ({ ariaControls, enableAnimations, isSelected, item, onSelect, }: MarketDetailsOutcomeButtonProps): JSX.Element;
11
+ ({ ariaControls, enableAnimations, enforceFixedWidth, isSelected, item, onSelect, }: MarketDetailsOutcomeButtonProps): JSX.Element;
11
12
  displayName: string;
12
13
  };
13
14
  export {};
@@ -2,12 +2,13 @@ import type { MarketDetailsHeaderOutcomeItem } from "./market-details.types";
2
2
  type MarketDetailsOutcomeButtonProps = {
3
3
  ariaControls?: string;
4
4
  enableAnimations: boolean;
5
+ enforceFixedWidth?: boolean;
5
6
  isSelected: boolean;
6
7
  item: MarketDetailsHeaderOutcomeItem;
7
8
  onSelect: (label: string) => void;
8
9
  };
9
10
  export declare const MarketDetailsOutcomeButton: {
10
- ({ ariaControls, enableAnimations, isSelected, item, onSelect, }: MarketDetailsOutcomeButtonProps): JSX.Element;
11
+ ({ ariaControls, enableAnimations, enforceFixedWidth, isSelected, item, onSelect, }: MarketDetailsOutcomeButtonProps): JSX.Element;
11
12
  displayName: string;
12
13
  };
13
14
  export {};
@@ -43,6 +43,35 @@ export type MarketDetailsBaseProps = {
43
43
  classNames?: MarketDetailsClassNames;
44
44
  /** Custom content rendered in the "other" tab. */
45
45
  otherContent?: React.ReactNode;
46
+ /**
47
+ * Optional content rendered between the card header (title + outcome pills)
48
+ * and the collapsible details body — visible whether or not the card is
49
+ * expanded. Used by the sports view to mount a spread/total line-selector
50
+ * rail on the same card that drives the order book / graph. Regular event
51
+ * markets omit it, so their layout is unchanged.
52
+ */
53
+ headerAccessory?: React.ReactNode;
54
+ /**
55
+ * Compact header treatment used by the sports view: hides the leading market
56
+ * thumbnail and the headline probability so the card reads as
57
+ * "{title} · {meta}" + outcome pills (matching the sports design). Defaults
58
+ * to `false`, so regular event markets keep the image + headline.
59
+ */
60
+ compactHeader?: boolean;
61
+ /**
62
+ * Optional subtitle override for custom surfaces (for example the sports
63
+ * compact header, which needs selected-option venue / volume metadata).
64
+ */
65
+ subtitleOverride?: string;
66
+ /**
67
+ * Optional header pill layout override. Sports cards use this to keep the
68
+ * market-specific sizing and line-label treatment isolated from the default
69
+ * market details header.
70
+ */
71
+ headerOutcomeVariant?: "outcome" | "line" | "yes_no";
72
+ /** Optional prebuilt header pills used when the card should render a custom
73
+ * market selection surface while keeping the regular details body. */
74
+ headerOutcomeItemsOverride?: MarketDetailsHeaderOutcomeItem[];
46
75
  /** Whether the market details should render a loading state. */
47
76
  isLoading?: boolean;
48
77
  /**
@@ -154,6 +183,8 @@ export type MarketDetailsHeaderOutcomeItem = {
154
183
  probability: number | undefined;
155
184
  tone: MarketDetailsOutcomeTone;
156
185
  venue: VenueLogoName;
186
+ variant?: "outcome" | "line" | "yes_no";
187
+ lineLabel?: string | null;
157
188
  };
158
189
  export type MarketDetailsOrderBookRow = {
159
190
  id: string;
@@ -43,6 +43,35 @@ export type MarketDetailsBaseProps = {
43
43
  classNames?: MarketDetailsClassNames;
44
44
  /** Custom content rendered in the "other" tab. */
45
45
  otherContent?: React.ReactNode;
46
+ /**
47
+ * Optional content rendered between the card header (title + outcome pills)
48
+ * and the collapsible details body — visible whether or not the card is
49
+ * expanded. Used by the sports view to mount a spread/total line-selector
50
+ * rail on the same card that drives the order book / graph. Regular event
51
+ * markets omit it, so their layout is unchanged.
52
+ */
53
+ headerAccessory?: React.ReactNode;
54
+ /**
55
+ * Compact header treatment used by the sports view: hides the leading market
56
+ * thumbnail and the headline probability so the card reads as
57
+ * "{title} · {meta}" + outcome pills (matching the sports design). Defaults
58
+ * to `false`, so regular event markets keep the image + headline.
59
+ */
60
+ compactHeader?: boolean;
61
+ /**
62
+ * Optional subtitle override for custom surfaces (for example the sports
63
+ * compact header, which needs selected-option venue / volume metadata).
64
+ */
65
+ subtitleOverride?: string;
66
+ /**
67
+ * Optional header pill layout override. Sports cards use this to keep the
68
+ * market-specific sizing and line-label treatment isolated from the default
69
+ * market details header.
70
+ */
71
+ headerOutcomeVariant?: "outcome" | "line" | "yes_no";
72
+ /** Optional prebuilt header pills used when the card should render a custom
73
+ * market selection surface while keeping the regular details body. */
74
+ headerOutcomeItemsOverride?: MarketDetailsHeaderOutcomeItem[];
46
75
  /** Whether the market details should render a loading state. */
47
76
  isLoading?: boolean;
48
77
  /**
@@ -154,6 +183,8 @@ export type MarketDetailsHeaderOutcomeItem = {
154
183
  probability: number | undefined;
155
184
  tone: MarketDetailsOutcomeTone;
156
185
  venue: VenueLogoName;
186
+ variant?: "outcome" | "line" | "yes_no";
187
+ lineLabel?: string | null;
157
188
  };
158
189
  export type MarketDetailsOrderBookRow = {
159
190
  id: string;
@@ -46,34 +46,21 @@ export declare const resolveScopedSelectedOutcome: ({ venueMarkets, selectedOutc
46
46
  export declare const resolveAverageProbabilityByLabel: (venueMarkets: VenueMarket[], labels: string[]) => Map<string, number | undefined>;
47
47
  export declare const formatProbabilityPercent: (value: number | null | undefined, formatPercent?: (value: number) => string) => string;
48
48
  export declare const resolveOutcomeTone: (label: string, index: number) => MarketDetailsOrderBookTone;
49
- export declare const resolveHeaderOutcomeItems: (venueMarkets: VenueMarket[], scopedMarket?: VenueMarket | null) => MarketDetailsHeaderOutcomeItem[];
50
- export declare const resolveSubtitle: ({ venueMarkets, volume, formatCompactCurrency, labels, tradableVenues, }: {
49
+ export declare const resolveHeaderOutcomeItems: (venueMarkets: VenueMarket[], scopedMarket?: VenueMarket | null, variant?: MarketDetailsHeaderOutcomeItem["variant"]) => MarketDetailsHeaderOutcomeItem[];
50
+ export declare const resolveSubtitle: ({ venueMarkets, volume, formatCompactCurrency, labels, }: {
51
51
  venueMarkets: VenueMarket[];
52
52
  volume: number | undefined;
53
53
  formatCompactCurrency: (value: number) => string;
54
54
  labels: AggUiLabels;
55
- /**
56
- * Optional runtime-derived set of venues that have a live orderbook.
57
- * Forwarded to `getVenueSummary` to filter `venueCount` to only
58
- * tradeable venues. When omitted the count includes all venues
59
- * regardless of orderbook availability.
60
- */
61
- tradableVenues?: ReadonlySet<string> | null;
62
55
  }) => string;
63
56
  export declare const resolveOtherTabRows: (market: ResolvedMarket, labels: AggUiLabels) => MarketDetailsMetaRow[];
64
- export declare const buildMarketDetailsModel: ({ venueMarkets, marketId, title, image, formatCompactCurrency, labels, tradableVenues, }: {
57
+ export declare const buildMarketDetailsModel: ({ venueMarkets, marketId, title, image, formatCompactCurrency, labels, }: {
65
58
  venueMarkets: VenueMarket[];
66
59
  marketId: string | undefined;
67
60
  title: string | undefined;
68
61
  image: string | null | undefined;
69
62
  formatCompactCurrency: (value: number) => string;
70
63
  labels: AggUiLabels;
71
- /**
72
- * Forwarded to `resolveSubtitle` → `getVenueSummary` so the "X venues"
73
- * subtitle reflects only venues with a live orderbook. Optional;
74
- * subtitle counts all cluster venues when omitted.
75
- */
76
- tradableVenues?: ReadonlySet<string> | null;
77
64
  }) => {
78
65
  market: ResolvedMarket;
79
66
  primaryVenueMarket: VenueMarket;
@@ -46,34 +46,21 @@ export declare const resolveScopedSelectedOutcome: ({ venueMarkets, selectedOutc
46
46
  export declare const resolveAverageProbabilityByLabel: (venueMarkets: VenueMarket[], labels: string[]) => Map<string, number | undefined>;
47
47
  export declare const formatProbabilityPercent: (value: number | null | undefined, formatPercent?: (value: number) => string) => string;
48
48
  export declare const resolveOutcomeTone: (label: string, index: number) => MarketDetailsOrderBookTone;
49
- export declare const resolveHeaderOutcomeItems: (venueMarkets: VenueMarket[], scopedMarket?: VenueMarket | null) => MarketDetailsHeaderOutcomeItem[];
50
- export declare const resolveSubtitle: ({ venueMarkets, volume, formatCompactCurrency, labels, tradableVenues, }: {
49
+ export declare const resolveHeaderOutcomeItems: (venueMarkets: VenueMarket[], scopedMarket?: VenueMarket | null, variant?: MarketDetailsHeaderOutcomeItem["variant"]) => MarketDetailsHeaderOutcomeItem[];
50
+ export declare const resolveSubtitle: ({ venueMarkets, volume, formatCompactCurrency, labels, }: {
51
51
  venueMarkets: VenueMarket[];
52
52
  volume: number | undefined;
53
53
  formatCompactCurrency: (value: number) => string;
54
54
  labels: AggUiLabels;
55
- /**
56
- * Optional runtime-derived set of venues that have a live orderbook.
57
- * Forwarded to `getVenueSummary` to filter `venueCount` to only
58
- * tradeable venues. When omitted the count includes all venues
59
- * regardless of orderbook availability.
60
- */
61
- tradableVenues?: ReadonlySet<string> | null;
62
55
  }) => string;
63
56
  export declare const resolveOtherTabRows: (market: ResolvedMarket, labels: AggUiLabels) => MarketDetailsMetaRow[];
64
- export declare const buildMarketDetailsModel: ({ venueMarkets, marketId, title, image, formatCompactCurrency, labels, tradableVenues, }: {
57
+ export declare const buildMarketDetailsModel: ({ venueMarkets, marketId, title, image, formatCompactCurrency, labels, }: {
65
58
  venueMarkets: VenueMarket[];
66
59
  marketId: string | undefined;
67
60
  title: string | undefined;
68
61
  image: string | null | undefined;
69
62
  formatCompactCurrency: (value: number) => string;
70
63
  labels: AggUiLabels;
71
- /**
72
- * Forwarded to `resolveSubtitle` → `getVenueSummary` so the "X venues"
73
- * subtitle reflects only venues with a live orderbook. Optional;
74
- * subtitle counts all cluster venues when omitted.
75
- */
76
- tradableVenues?: ReadonlySet<string> | null;
77
64
  }) => {
78
65
  market: ResolvedMarket;
79
66
  primaryVenueMarket: VenueMarket;
@@ -0,0 +1,24 @@
1
+ type EventCategoryLike = {
2
+ id?: string | null;
3
+ category?: {
4
+ id?: string | null;
5
+ name?: string | null;
6
+ displayName?: string | null;
7
+ parentId?: string | null;
8
+ } | null;
9
+ };
10
+ type FormatEventTitleWithDateSuffixParams = {
11
+ title: string;
12
+ categories?: readonly EventCategoryLike[] | null;
13
+ structureType?: string | null;
14
+ /**
15
+ * Scheduled kickoff of the underlying game. Preferred over `endDate` for
16
+ * the date suffix because `endDate` is the market close/expiration, which
17
+ * can sit well after the game (e.g. Kalshi World Cup markets expire weeks
18
+ * later — a June 22 game would otherwise read "- July 6").
19
+ */
20
+ gameStartTime?: string | null;
21
+ endDate?: string | null;
22
+ };
23
+ export declare const formatEventTitleWithDateSuffix: ({ title, categories, structureType, gameStartTime, endDate, }: FormatEventTitleWithDateSuffixParams) => string;
24
+ export {};
@@ -0,0 +1,24 @@
1
+ type EventCategoryLike = {
2
+ id?: string | null;
3
+ category?: {
4
+ id?: string | null;
5
+ name?: string | null;
6
+ displayName?: string | null;
7
+ parentId?: string | null;
8
+ } | null;
9
+ };
10
+ type FormatEventTitleWithDateSuffixParams = {
11
+ title: string;
12
+ categories?: readonly EventCategoryLike[] | null;
13
+ structureType?: string | null;
14
+ /**
15
+ * Scheduled kickoff of the underlying game. Preferred over `endDate` for
16
+ * the date suffix because `endDate` is the market close/expiration, which
17
+ * can sit well after the game (e.g. Kalshi World Cup markets expire weeks
18
+ * later — a June 22 game would otherwise read "- July 6").
19
+ */
20
+ gameStartTime?: string | null;
21
+ endDate?: string | null;
22
+ };
23
+ export declare const formatEventTitleWithDateSuffix: ({ title, categories, structureType, gameStartTime, endDate, }: FormatEventTitleWithDateSuffixParams) => string;
24
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare const SPORTS_EVENT_TIMEZONE = "America/New_York";
2
+ export declare const formatSportsEventTimeEt: (value: string) => string | null;
@@ -0,0 +1,2 @@
1
+ export declare const SPORTS_EVENT_TIMEZONE = "America/New_York";
2
+ export declare const formatSportsEventTimeEt: (value: string) => string | null;
@@ -0,0 +1,88 @@
1
+ import type { LiveBestPriceCandidate } from "@agg-build/hooks";
2
+ /** Which data tier produced the winning price + venue. */
3
+ export type BestOutcomeSource = "ws" | "rest-best" | "rest-midpoint" | "static";
4
+ /**
5
+ * The single, unified result for an outcome pill: price and venue resolved
6
+ * together from the *same* tier, so the displayed price and the venue logo can
7
+ * never disagree. `venueMarketId`, `source` and `updatedAt` are carried for
8
+ * telemetry/debugging and to let callers reason about freshness.
9
+ */
10
+ export interface BestOutcomeCandidate {
11
+ price: number;
12
+ venue: string | undefined;
13
+ venueMarketId: string | undefined;
14
+ outcomeId: string;
15
+ source: BestOutcomeSource;
16
+ updatedAt: number | undefined;
17
+ }
18
+ export interface SelectBestOutcomeArgs {
19
+ outcomeId: string | null | undefined;
20
+ outcomeLabel?: string | null | undefined;
21
+ /** Active trade side. When set, the best ask (buy) / best bid (sell) wins. */
22
+ selection?: "buy" | "sell" | undefined;
23
+ /**
24
+ * Live WS candidate for this outcome — already folded across all venues for
25
+ * the outcome's MVMO group (see `buildLiveBestPriceCandidates`). Carries the
26
+ * venue that owns each side, so when a different venue takes the best live
27
+ * price the logo follows the price.
28
+ */
29
+ live?: LiveBestPriceCandidate | null | undefined;
30
+ /** REST cross-venue best bid/ask (fallback when WS hasn't landed). */
31
+ restBest?: {
32
+ bestBid?: number;
33
+ bestAsk?: number;
34
+ } | null | undefined;
35
+ /** REST venue that produced each side of `restBest`. */
36
+ restBestVenues?: {
37
+ bestBidVenue?: string;
38
+ bestAskVenue?: string;
39
+ } | null | undefined;
40
+ /** REST per-outcome midpoint (display-path fallback). */
41
+ restMidpoint?: number | null | undefined;
42
+ /** Venue that produced `restMidpoint`. */
43
+ restMidpointVenue?: string | null | undefined;
44
+ /** Cluster-wide "Yes" reference midpoint (display path, "yes" labels only). */
45
+ bestMidpoint?: number | null | undefined;
46
+ /** Venue that produced `bestMidpoint`. */
47
+ bestMidpointVenue?: string | null | undefined;
48
+ /** Final static fallback — the outcome's payload price. */
49
+ staticPrice?: number | null | undefined;
50
+ /** Venue for the static fallback (typically the local market's own venue). */
51
+ staticVenue?: string | null | undefined;
52
+ /** Resolves a venue name → its venueMarketId within the cluster (best effort). */
53
+ venueMarketIdByVenue?: ReadonlyMap<string, string> | null | undefined;
54
+ }
55
+ /**
56
+ * Resolve the single best price + venue for an outcome across all venues.
57
+ *
58
+ * Candidate priority (price and venue are always taken from the SAME tier):
59
+ * With a trade selection (buy/sell):
60
+ * 1. fresh WS best ask/bid for that side → source "ws"
61
+ * 2. REST best ask/bid for that side → source "rest-best"
62
+ * 3. fresh WS midpoint → source "ws"
63
+ * 4. REST per-outcome midpoint → source "rest-midpoint"
64
+ * 5. static outcome price → source "static"
65
+ * Display path (no selection):
66
+ * 1. fresh WS midpoint → source "ws"
67
+ * 2. cluster "Yes" reference (yes labels) → source "rest-midpoint"
68
+ * 3. REST per-outcome midpoint → source "rest-midpoint"
69
+ * 4. static outcome price → source "static"
70
+ *
71
+ * Because WS is preferred per side over REST, a stale REST snapshot can never
72
+ * override newer live data — and because the venue is read from whichever tier
73
+ * supplied the price, the logo and the price switch together.
74
+ */
75
+ export declare const selectBestOutcomeCandidate: (args: SelectBestOutcomeArgs) => BestOutcomeCandidate | undefined;
76
+ /**
77
+ * Build a venue-name → venueMarketId lookup across a cluster (including matched
78
+ * siblings). First occurrence wins. Used to resolve the winning venue's market
79
+ * id for {@link selectBestOutcomeCandidate}.
80
+ */
81
+ export declare const buildVenueMarketIdByVenue: (venueMarkets: ReadonlyArray<{
82
+ id?: string;
83
+ venue?: string | null;
84
+ matchedVenueMarkets?: ReadonlyArray<{
85
+ id?: string;
86
+ venue?: string | null;
87
+ }> | null;
88
+ }> | null | undefined) => Map<string, string>;
@@ -0,0 +1,88 @@
1
+ import type { LiveBestPriceCandidate } from "@agg-build/hooks";
2
+ /** Which data tier produced the winning price + venue. */
3
+ export type BestOutcomeSource = "ws" | "rest-best" | "rest-midpoint" | "static";
4
+ /**
5
+ * The single, unified result for an outcome pill: price and venue resolved
6
+ * together from the *same* tier, so the displayed price and the venue logo can
7
+ * never disagree. `venueMarketId`, `source` and `updatedAt` are carried for
8
+ * telemetry/debugging and to let callers reason about freshness.
9
+ */
10
+ export interface BestOutcomeCandidate {
11
+ price: number;
12
+ venue: string | undefined;
13
+ venueMarketId: string | undefined;
14
+ outcomeId: string;
15
+ source: BestOutcomeSource;
16
+ updatedAt: number | undefined;
17
+ }
18
+ export interface SelectBestOutcomeArgs {
19
+ outcomeId: string | null | undefined;
20
+ outcomeLabel?: string | null | undefined;
21
+ /** Active trade side. When set, the best ask (buy) / best bid (sell) wins. */
22
+ selection?: "buy" | "sell" | undefined;
23
+ /**
24
+ * Live WS candidate for this outcome — already folded across all venues for
25
+ * the outcome's MVMO group (see `buildLiveBestPriceCandidates`). Carries the
26
+ * venue that owns each side, so when a different venue takes the best live
27
+ * price the logo follows the price.
28
+ */
29
+ live?: LiveBestPriceCandidate | null | undefined;
30
+ /** REST cross-venue best bid/ask (fallback when WS hasn't landed). */
31
+ restBest?: {
32
+ bestBid?: number;
33
+ bestAsk?: number;
34
+ } | null | undefined;
35
+ /** REST venue that produced each side of `restBest`. */
36
+ restBestVenues?: {
37
+ bestBidVenue?: string;
38
+ bestAskVenue?: string;
39
+ } | null | undefined;
40
+ /** REST per-outcome midpoint (display-path fallback). */
41
+ restMidpoint?: number | null | undefined;
42
+ /** Venue that produced `restMidpoint`. */
43
+ restMidpointVenue?: string | null | undefined;
44
+ /** Cluster-wide "Yes" reference midpoint (display path, "yes" labels only). */
45
+ bestMidpoint?: number | null | undefined;
46
+ /** Venue that produced `bestMidpoint`. */
47
+ bestMidpointVenue?: string | null | undefined;
48
+ /** Final static fallback — the outcome's payload price. */
49
+ staticPrice?: number | null | undefined;
50
+ /** Venue for the static fallback (typically the local market's own venue). */
51
+ staticVenue?: string | null | undefined;
52
+ /** Resolves a venue name → its venueMarketId within the cluster (best effort). */
53
+ venueMarketIdByVenue?: ReadonlyMap<string, string> | null | undefined;
54
+ }
55
+ /**
56
+ * Resolve the single best price + venue for an outcome across all venues.
57
+ *
58
+ * Candidate priority (price and venue are always taken from the SAME tier):
59
+ * With a trade selection (buy/sell):
60
+ * 1. fresh WS best ask/bid for that side → source "ws"
61
+ * 2. REST best ask/bid for that side → source "rest-best"
62
+ * 3. fresh WS midpoint → source "ws"
63
+ * 4. REST per-outcome midpoint → source "rest-midpoint"
64
+ * 5. static outcome price → source "static"
65
+ * Display path (no selection):
66
+ * 1. fresh WS midpoint → source "ws"
67
+ * 2. cluster "Yes" reference (yes labels) → source "rest-midpoint"
68
+ * 3. REST per-outcome midpoint → source "rest-midpoint"
69
+ * 4. static outcome price → source "static"
70
+ *
71
+ * Because WS is preferred per side over REST, a stale REST snapshot can never
72
+ * override newer live data — and because the venue is read from whichever tier
73
+ * supplied the price, the logo and the price switch together.
74
+ */
75
+ export declare const selectBestOutcomeCandidate: (args: SelectBestOutcomeArgs) => BestOutcomeCandidate | undefined;
76
+ /**
77
+ * Build a venue-name → venueMarketId lookup across a cluster (including matched
78
+ * siblings). First occurrence wins. Used to resolve the winning venue's market
79
+ * id for {@link selectBestOutcomeCandidate}.
80
+ */
81
+ export declare const buildVenueMarketIdByVenue: (venueMarkets: ReadonlyArray<{
82
+ id?: string;
83
+ venue?: string | null;
84
+ matchedVenueMarkets?: ReadonlyArray<{
85
+ id?: string;
86
+ venue?: string | null;
87
+ }> | null;
88
+ }> | null | undefined) => Map<string, string>;