@m3000/market 0.0.1

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 (154) hide show
  1. package/LICENSE +21 -0
  2. package/dist/components/blocks/auction/Auction.d.ts +49 -0
  3. package/dist/components/blocks/auction/Auction.js +44 -0
  4. package/dist/components/blocks/auction/AuctionBidForm.d.ts +11 -0
  5. package/dist/components/blocks/auction/AuctionBidForm.js +88 -0
  6. package/dist/components/blocks/auction/AuctionBidInput.d.ts +9 -0
  7. package/dist/components/blocks/auction/AuctionBidInput.js +99 -0
  8. package/dist/components/blocks/auction/AuctionContext.d.ts +71 -0
  9. package/dist/components/blocks/auction/AuctionContext.js +228 -0
  10. package/dist/components/blocks/auction/AuctionInfo.d.ts +9 -0
  11. package/dist/components/blocks/auction/AuctionInfo.js +37 -0
  12. package/dist/components/blocks/auction/AuctionLayout.d.ts +63 -0
  13. package/dist/components/blocks/auction/AuctionLayout.js +80 -0
  14. package/dist/components/blocks/auction/AuctionRankings.d.ts +16 -0
  15. package/dist/components/blocks/auction/AuctionRankings.js +334 -0
  16. package/dist/components/blocks/auction/AuctionStatusTag.d.ts +15 -0
  17. package/dist/components/blocks/auction/AuctionStatusTag.js +60 -0
  18. package/dist/components/blocks/auction/AuctionSuggestedBids.d.ts +38 -0
  19. package/dist/components/blocks/auction/AuctionSuggestedBids.js +116 -0
  20. package/dist/components/blocks/auction/AuctionYourBidCard.d.ts +27 -0
  21. package/dist/components/blocks/auction/AuctionYourBidCard.js +94 -0
  22. package/dist/components/blocks/auction/AuctionYourBids.d.ts +9 -0
  23. package/dist/components/blocks/auction/AuctionYourBids.js +49 -0
  24. package/dist/components/blocks/auction/index.d.ts +12 -0
  25. package/dist/components/blocks/index.d.ts +12 -0
  26. package/dist/components/index.d.ts +28 -0
  27. package/dist/components/primitives/Button.d.ts +31 -0
  28. package/dist/components/primitives/Button.js +117 -0
  29. package/dist/components/primitives/Drawer.d.ts +43 -0
  30. package/dist/components/primitives/Drawer.js +51 -0
  31. package/dist/components/primitives/Feedback.d.ts +28 -0
  32. package/dist/components/primitives/Feedback.js +147 -0
  33. package/dist/components/primitives/MorphDialog.d.ts +39 -0
  34. package/dist/components/primitives/MorphDialog.js +87 -0
  35. package/dist/components/primitives/Price.d.ts +84 -0
  36. package/dist/components/primitives/Price.js +255 -0
  37. package/dist/components/primitives/PriceInput.d.ts +33 -0
  38. package/dist/components/primitives/PriceInput.js +25 -0
  39. package/dist/components/primitives/Receipt.d.ts +164 -0
  40. package/dist/components/primitives/Receipt.js +344 -0
  41. package/dist/components/primitives/Scale.d.ts +67 -0
  42. package/dist/components/primitives/Scale.js +132 -0
  43. package/dist/components/primitives/Separator.d.ts +22 -0
  44. package/dist/components/primitives/Separator.js +62 -0
  45. package/dist/components/primitives/Skeleton.d.ts +14 -0
  46. package/dist/components/primitives/Skeleton.js +20 -0
  47. package/dist/components/primitives/SteppedInput.d.ts +94 -0
  48. package/dist/components/primitives/SteppedInput.js +154 -0
  49. package/dist/components/primitives/Tabs.d.ts +37 -0
  50. package/dist/components/primitives/Tabs.js +99 -0
  51. package/dist/components/primitives/Tag.d.ts +24 -0
  52. package/dist/components/primitives/Tag.js +22 -0
  53. package/dist/components/primitives/Text.d.ts +32 -0
  54. package/dist/components/primitives/Text.js +65 -0
  55. package/dist/components/primitives/countdown/Countdown.d.ts +24 -0
  56. package/dist/components/primitives/countdown/Countdown.js +22 -0
  57. package/dist/components/primitives/framed-image/FramedImage.d.ts +13 -0
  58. package/dist/components/primitives/framed-image/FramedImage.js +37 -0
  59. package/dist/components/primitives/index.d.ts +17 -0
  60. package/dist/components/primitives/ranked-list/Ranking.d.ts +117 -0
  61. package/dist/components/primitives/ranked-list/Ranking.js +219 -0
  62. package/dist/components/primitives/ranked-list/index.d.ts +1 -0
  63. package/dist/hooks/useCountdown.d.ts +20 -0
  64. package/dist/hooks/useCountdown.js +75 -0
  65. package/dist/index.d.ts +36 -0
  66. package/dist/index.js +36 -0
  67. package/dist/lib/cn.d.ts +6 -0
  68. package/dist/lib/cn.js +75 -0
  69. package/dist/lib/motion.d.ts +19 -0
  70. package/dist/lib/motion.js +43 -0
  71. package/dist/types/index.d.ts +120 -0
  72. package/dist/utils/format.d.ts +38 -0
  73. package/dist/utils/format.js +103 -0
  74. package/dist/utils/rank-utils.d.ts +34 -0
  75. package/dist/utils/rank-utils.js +80 -0
  76. package/dist/utils/tick-validation.d.ts +22 -0
  77. package/dist/utils/tick-validation.js +40 -0
  78. package/package.json +92 -0
  79. package/src/components/blocks/auction/Auction.tsx +74 -0
  80. package/src/components/blocks/auction/AuctionArtwork.tsx +4 -0
  81. package/src/components/blocks/auction/AuctionBidForm.tsx +138 -0
  82. package/src/components/blocks/auction/AuctionBidInput.tsx +166 -0
  83. package/src/components/blocks/auction/AuctionContext.tsx +401 -0
  84. package/src/components/blocks/auction/AuctionInfo.tsx +36 -0
  85. package/src/components/blocks/auction/AuctionLayout.tsx +200 -0
  86. package/src/components/blocks/auction/AuctionRankings.tsx +435 -0
  87. package/src/components/blocks/auction/AuctionStatusTag.tsx +98 -0
  88. package/src/components/blocks/auction/AuctionSuggestedBids.tsx +203 -0
  89. package/src/components/blocks/auction/AuctionYourBidCard.tsx +125 -0
  90. package/src/components/blocks/auction/AuctionYourBids.tsx +61 -0
  91. package/src/components/blocks/auction/index.ts +42 -0
  92. package/src/components/blocks/index.ts +1 -0
  93. package/src/components/index.ts +2 -0
  94. package/src/components/primitives/Button.tsx +183 -0
  95. package/src/components/primitives/Drawer.tsx +125 -0
  96. package/src/components/primitives/Feedback.tsx +185 -0
  97. package/src/components/primitives/MorphDialog.tsx +160 -0
  98. package/src/components/primitives/Price.tsx +394 -0
  99. package/src/components/primitives/PriceInput.tsx +48 -0
  100. package/src/components/primitives/Receipt.tsx +711 -0
  101. package/src/components/primitives/Scale.tsx +287 -0
  102. package/src/components/primitives/Separator.tsx +87 -0
  103. package/src/components/primitives/Skeleton.tsx +33 -0
  104. package/src/components/primitives/SteppedInput.tsx +313 -0
  105. package/src/components/primitives/Tabs.tsx +161 -0
  106. package/src/components/primitives/Tag.tsx +48 -0
  107. package/src/components/primitives/Text.tsx +102 -0
  108. package/src/components/primitives/countdown/Countdown.tsx +43 -0
  109. package/src/components/primitives/countdown/index.ts +2 -0
  110. package/src/components/primitives/framed-image/FramedImage.tsx +51 -0
  111. package/src/components/primitives/framed-image/index.ts +1 -0
  112. package/src/components/primitives/index.ts +42 -0
  113. package/src/components/primitives/ranked-list/RankedList.tsx +9 -0
  114. package/src/components/primitives/ranked-list/Ranking.tsx +454 -0
  115. package/src/components/primitives/ranked-list/index.ts +8 -0
  116. package/src/hooks/index.ts +1 -0
  117. package/src/hooks/useCountdown.ts +91 -0
  118. package/src/index.ts +130 -0
  119. package/src/lib/cn.ts +81 -0
  120. package/src/lib/index.ts +2 -0
  121. package/src/lib/motion.ts +55 -0
  122. package/src/public/lea-83-time-walk.png +0 -0
  123. package/src/public/lea-83-time-walk.webp +0 -0
  124. package/src/stories/Auction.stories.tsx +658 -0
  125. package/src/stories/AuctionLayout.stories.tsx +313 -0
  126. package/src/stories/AuctionStatusTag.stories.tsx +166 -0
  127. package/src/stories/AuctionYourBidCard.stories.tsx +257 -0
  128. package/src/stories/Button.stories.tsx +306 -0
  129. package/src/stories/Countdown.stories.tsx +158 -0
  130. package/src/stories/Feedback.stories.tsx +80 -0
  131. package/src/stories/FramedImage.stories.tsx +46 -0
  132. package/src/stories/MorphDialog.stories.tsx +88 -0
  133. package/src/stories/Price.stories.tsx +292 -0
  134. package/src/stories/RankedList.stories.tsx +190 -0
  135. package/src/stories/Receipt.stories.tsx +221 -0
  136. package/src/stories/Scale.stories.tsx +578 -0
  137. package/src/stories/Separator.stories.tsx +188 -0
  138. package/src/stories/Skeleton.stories.tsx +138 -0
  139. package/src/stories/SteppedInput.stories.tsx +321 -0
  140. package/src/stories/Tabs.stories.tsx +215 -0
  141. package/src/stories/Tag.stories.tsx +138 -0
  142. package/src/stories/Text.stories.tsx +245 -0
  143. package/src/styles/globals.css +39 -0
  144. package/src/styles/index.css +4 -0
  145. package/src/styles/theme/animation.css +11 -0
  146. package/src/styles/theme/color.css +185 -0
  147. package/src/styles/theme/index.css +3 -0
  148. package/src/styles/theme/typography.css +3 -0
  149. package/src/styles/utility.css +8 -0
  150. package/src/types/index.ts +149 -0
  151. package/src/utils/format.ts +130 -0
  152. package/src/utils/index.ts +16 -0
  153. package/src/utils/rank-utils.ts +131 -0
  154. package/src/utils/tick-validation.ts +65 -0
@@ -0,0 +1,63 @@
1
+ import { ReactNode } from "react";
2
+
3
+ //#region src/components/blocks/auction/AuctionLayout.d.ts
4
+ interface AuctionLayoutProps {
5
+ children: ReactNode;
6
+ className?: string;
7
+ height?: string | number;
8
+ }
9
+ declare function AuctionLayout({
10
+ children,
11
+ className,
12
+ height
13
+ }: AuctionLayoutProps): React.ReactElement;
14
+ interface AuctionDetailsProps {
15
+ children: ReactNode;
16
+ className?: string;
17
+ }
18
+ declare function AuctionDetails({
19
+ children,
20
+ className
21
+ }: AuctionDetailsProps): React.ReactElement;
22
+ interface AuctionDetailsHeaderProps {
23
+ children: ReactNode;
24
+ className?: string;
25
+ }
26
+ declare function AuctionDetailsHeader({
27
+ children,
28
+ className
29
+ }: AuctionDetailsHeaderProps): React.ReactElement;
30
+ interface AuctionDetailsBodyProps {
31
+ children: ReactNode;
32
+ className?: string;
33
+ }
34
+ declare function AuctionDetailsBody({
35
+ children,
36
+ className
37
+ }: AuctionDetailsBodyProps): React.ReactElement;
38
+ interface AuctionDetailsFooterProps {
39
+ children: ReactNode;
40
+ className?: string;
41
+ }
42
+ declare function AuctionDetailsFooter({
43
+ children,
44
+ className
45
+ }: AuctionDetailsFooterProps): React.ReactElement;
46
+ interface AuctionRankingsContainerProps {
47
+ children: ReactNode;
48
+ className?: string;
49
+ }
50
+ declare function AuctionRankingsContainer({
51
+ children,
52
+ className
53
+ }: AuctionRankingsContainerProps): React.ReactElement;
54
+ interface AuctionBiddingPanelProps {
55
+ children: ReactNode;
56
+ className?: string;
57
+ }
58
+ declare function AuctionBiddingPanel({
59
+ children,
60
+ className
61
+ }: AuctionBiddingPanelProps): React.ReactElement;
62
+ //#endregion
63
+ export { AuctionBiddingPanel, AuctionBiddingPanelProps, AuctionDetails, AuctionDetailsBody, AuctionDetailsBodyProps, AuctionDetailsFooter, AuctionDetailsFooterProps, AuctionDetailsHeader, AuctionDetailsHeaderProps, AuctionDetailsProps, AuctionLayout, AuctionLayoutProps, AuctionRankingsContainer, AuctionRankingsContainerProps };
@@ -0,0 +1,80 @@
1
+ "use client";
2
+
3
+ import { useAuctionContext } from "./AuctionContext.js";
4
+ import { cn } from "../../../lib/cn.js";
5
+ import { Button } from "../../primitives/Button.js";
6
+ import { jsx } from "react/jsx-runtime";
7
+
8
+ //#region src/components/blocks/auction/AuctionLayout.tsx
9
+ function AuctionLayout({ children, className, height = "calc(100vh - 4rem)" }) {
10
+ const heightStyle = typeof height === "number" ? `${height}px` : height;
11
+ const { isBiddingActive } = useAuctionContext();
12
+ return /* @__PURE__ */ jsx("div", {
13
+ className: cn("relative grid overflow-hidden grid-rows-[minmax(0,1fr)_minmax(0,1fr)]", isBiddingActive && "grid-rows-1", "lg:grid-cols-2 lg:grid-rows-1", className),
14
+ style: { height: heightStyle },
15
+ children
16
+ });
17
+ }
18
+ function AuctionDetails({ children, className }) {
19
+ const { isBiddingActive } = useAuctionContext();
20
+ return /* @__PURE__ */ jsx("div", {
21
+ className: cn("relative flex h-full min-h-0 flex-col overflow-hidden", "border-border", "lg:border-r", isBiddingActive && "overflow-hidden", className),
22
+ children
23
+ });
24
+ }
25
+ function AuctionDetailsHeader({ children, className }) {
26
+ const { isBiddingActive } = useAuctionContext();
27
+ return /* @__PURE__ */ jsx("div", {
28
+ className: cn("flex min-h-0 grow flex-col p-6", isBiddingActive && [
29
+ "max-lg:overflow-hidden",
30
+ "max-lg:[&>*:nth-child(n+3):not(:last-child)]:hidden",
31
+ "max-lg:[&>*:last-child]:pointer-events-none",
32
+ "max-lg:[&>*:last-child]:absolute",
33
+ "max-lg:[&>*:last-child]:inset-x-6",
34
+ "max-lg:[&>*:last-child]:bottom-6",
35
+ "max-lg:[&>*:last-child]:top-28",
36
+ "max-lg:[&>*:last-child]:min-h-0",
37
+ "max-lg:[&>*:last-child]:overflow-hidden"
38
+ ].join(" "), className),
39
+ children
40
+ });
41
+ }
42
+ function AuctionDetailsBody({ children, className }) {
43
+ return /* @__PURE__ */ jsx("div", {
44
+ className: cn("hidden p-6 lg:block lg:min-h-0 lg:flex-1 lg:overflow-y-auto", className),
45
+ children
46
+ });
47
+ }
48
+ function AuctionDetailsFooter({ children, className }) {
49
+ return /* @__PURE__ */ jsx("div", {
50
+ className: cn("mt-auto shrink-0 border-t border-border p-6", className),
51
+ children
52
+ });
53
+ }
54
+ function AuctionRankingsContainer({ children, className }) {
55
+ const { isBiddingActive } = useAuctionContext();
56
+ return /* @__PURE__ */ jsx("div", {
57
+ className: cn("grid h-full min-h-0 grid-rows-[minmax(0,1fr)_auto]", isBiddingActive && "max-lg:absolute max-lg:inset-x-0 max-lg:bottom-0 max-lg:top-0 max-lg:z-20 max-lg:overflow-hidden max-lg:rounded-t-[1.75rem] max-lg:border-t max-lg:border-border max-lg:bg-background/95 max-lg:shadow-2xl max-lg:backdrop-blur-sm", className),
58
+ children
59
+ });
60
+ }
61
+ function AuctionBiddingPanel({ children, className }) {
62
+ const { isBiddingActive, startBidding, isAuctionEnded, setShowBidPreview } = useAuctionContext();
63
+ const handleStartBidding = () => {
64
+ startBidding();
65
+ setShowBidPreview(true);
66
+ };
67
+ return /* @__PURE__ */ jsx("div", {
68
+ className: cn("row-start-2 rounded-t-[1.75rem] border-t border-border bg-background p-6 lg:rounded-xl", className),
69
+ children: !isBiddingActive ? /* @__PURE__ */ jsx(Button, {
70
+ className: "w-full",
71
+ size: "lg",
72
+ disabled: isAuctionEnded,
73
+ onClick: handleStartBidding,
74
+ children: isAuctionEnded ? "Auction Ended" : "Start Bidding"
75
+ }) : children
76
+ });
77
+ }
78
+
79
+ //#endregion
80
+ export { AuctionBiddingPanel, AuctionDetails, AuctionDetailsBody, AuctionDetailsFooter, AuctionDetailsHeader, AuctionLayout, AuctionRankingsContainer };
@@ -0,0 +1,16 @@
1
+ import { AuctionBid } from "../../../types/index.js";
2
+ import { GroupItemContextValue } from "../../primitives/ranked-list/Ranking.js";
3
+ //#region src/components/blocks/auction/AuctionRankings.d.ts
4
+ interface AuctionRankingsProps {
5
+ className?: string;
6
+ renderBidRow?: (bid: AuctionBid, context: GroupItemContextValue<AuctionBid> & {
7
+ isOutbid: boolean;
8
+ }) => React.ReactNode;
9
+ }
10
+ declare function RankingsSkeleton(): React.ReactElement;
11
+ declare function AuctionRankings({
12
+ className,
13
+ renderBidRow
14
+ }: AuctionRankingsProps): React.ReactElement;
15
+ //#endregion
16
+ export { AuctionRankings, AuctionRankingsProps, RankingsSkeleton };
@@ -0,0 +1,334 @@
1
+ "use client";
2
+
3
+ import { formatShortRelative } from "../../../utils/format.js";
4
+ import { getProjectedRankForPrice } from "../../../utils/rank-utils.js";
5
+ import { useAuctionContext } from "./AuctionContext.js";
6
+ import { cn } from "../../../lib/cn.js";
7
+ import { Button } from "../../primitives/Button.js";
8
+ import { Text } from "../../primitives/Text.js";
9
+ import { Separator } from "../../primitives/Separator.js";
10
+ import { Ranking } from "../../primitives/ranked-list/Ranking.js";
11
+ import { Skeleton } from "../../primitives/Skeleton.js";
12
+ import { useEffect, useMemo, useRef } from "react";
13
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
+
15
+ //#region src/components/blocks/auction/AuctionRankings.tsx
16
+ function BidRow({ bid, rank, isOutbid, isUserBid, onTopUp, isAuctionEnded, formatPrice, currencySymbol }) {
17
+ const timeShort = formatShortRelative(bid.createdAt);
18
+ return /* @__PURE__ */ jsxs("div", {
19
+ className: cn("flex items-center justify-between gap-2 px-6 py-2", isOutbid && "opacity-50", isUserBid && "shadow-[inset_2px_0_0_0_var(--color-primary)]"),
20
+ children: [/* @__PURE__ */ jsxs("div", {
21
+ className: "flex min-w-0 items-center gap-3",
22
+ children: [/* @__PURE__ */ jsxs(Text, {
23
+ color: "tertiary",
24
+ className: "w-8 shrink-0",
25
+ size: "1",
26
+ children: ["#", rank]
27
+ }), /* @__PURE__ */ jsxs("span", {
28
+ className: "flex min-w-0 items-center gap-3",
29
+ children: [bid.bidder.avatarUrl && /* @__PURE__ */ jsx("img", {
30
+ src: bid.bidder.avatarUrl,
31
+ alt: "",
32
+ className: "size-6 shrink-0 rounded-full object-cover"
33
+ }), /* @__PURE__ */ jsx(Text, {
34
+ className: "truncate",
35
+ children: isUserBid ? "You" : bid.bidder.name || `${bid.bidder.id.slice(0, 6)}...`
36
+ })]
37
+ })]
38
+ }), /* @__PURE__ */ jsxs("div", {
39
+ className: "flex shrink-0 items-center gap-4",
40
+ children: [
41
+ isUserBid && !isAuctionEnded && /* @__PURE__ */ jsx(Button, {
42
+ size: "xs",
43
+ color: "secondary",
44
+ onClick: onTopUp,
45
+ children: "Top up"
46
+ }),
47
+ /* @__PURE__ */ jsxs(Text, { children: [
48
+ formatPrice(bid.price),
49
+ " ",
50
+ currencySymbol
51
+ ] }),
52
+ /* @__PURE__ */ jsx(Text, {
53
+ size: "1",
54
+ color: "tertiary",
55
+ className: "min-w-9 text-right tabular-nums",
56
+ suppressHydrationWarning: true,
57
+ children: timeShort
58
+ })
59
+ ]
60
+ })]
61
+ });
62
+ }
63
+ function BidPreviewRow({ price, rank, onCancel, formatPrice, currencySymbol, previewRef }) {
64
+ return /* @__PURE__ */ jsxs("div", {
65
+ ref: previewRef,
66
+ className: "relative",
67
+ children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-0 animate-[pulse_2s_ease-in-out_infinite] bg-success/10" }), /* @__PURE__ */ jsxs("div", {
68
+ className: "relative flex items-center justify-between gap-2 px-6 py-2",
69
+ children: [/* @__PURE__ */ jsxs("div", {
70
+ className: "flex min-w-0 items-center gap-3",
71
+ children: [/* @__PURE__ */ jsxs(Text, {
72
+ color: "tertiary",
73
+ className: "w-8 shrink-0",
74
+ size: "1",
75
+ children: ["#", rank]
76
+ }), /* @__PURE__ */ jsx("span", {
77
+ className: "flex min-w-0 items-center gap-3",
78
+ children: /* @__PURE__ */ jsx(Text, {
79
+ color: "secondary",
80
+ children: "New bid preview"
81
+ })
82
+ })]
83
+ }), /* @__PURE__ */ jsxs("div", {
84
+ className: "flex shrink-0 items-center gap-4",
85
+ children: [
86
+ /* @__PURE__ */ jsx(Button, {
87
+ size: "xs",
88
+ color: "tertiary",
89
+ onClick: onCancel,
90
+ children: "Cancel"
91
+ }),
92
+ /* @__PURE__ */ jsxs(Text, {
93
+ weight: "medium",
94
+ tabularNums: true,
95
+ children: [
96
+ formatPrice(price),
97
+ " ",
98
+ currencySymbol
99
+ ]
100
+ }),
101
+ /* @__PURE__ */ jsx("span", { className: "min-w-9" })
102
+ ]
103
+ })]
104
+ })]
105
+ });
106
+ }
107
+ function TopUpPreviewRow({ price, rank, onCancel, formatPrice, currencySymbol }) {
108
+ return /* @__PURE__ */ jsxs("div", {
109
+ className: "relative shadow-[inset_2px_0_0_0_var(--color-success)]",
110
+ children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-0 animate-[pulse_2s_ease-in-out_infinite] bg-success/10" }), /* @__PURE__ */ jsxs("div", {
111
+ className: "relative flex items-center justify-between gap-2 px-6 py-2",
112
+ children: [/* @__PURE__ */ jsxs("div", {
113
+ className: "flex min-w-0 items-center gap-3",
114
+ children: [/* @__PURE__ */ jsxs(Text, {
115
+ color: "tertiary",
116
+ className: "w-8 shrink-0",
117
+ size: "1",
118
+ children: ["#", rank]
119
+ }), /* @__PURE__ */ jsx("span", {
120
+ className: "flex min-w-0 items-center gap-3",
121
+ children: /* @__PURE__ */ jsx(Text, {
122
+ color: "secondary",
123
+ children: "Top-up preview"
124
+ })
125
+ })]
126
+ }), /* @__PURE__ */ jsxs("div", {
127
+ className: "flex shrink-0 items-center gap-4",
128
+ children: [
129
+ /* @__PURE__ */ jsx(Button, {
130
+ size: "xs",
131
+ color: "tertiary",
132
+ onClick: onCancel,
133
+ children: "Cancel"
134
+ }),
135
+ /* @__PURE__ */ jsxs(Text, {
136
+ weight: "medium",
137
+ tabularNums: true,
138
+ children: [
139
+ formatPrice(price),
140
+ " ",
141
+ currencySymbol
142
+ ]
143
+ }),
144
+ /* @__PURE__ */ jsx("span", { className: "min-w-9" })
145
+ ]
146
+ })]
147
+ })]
148
+ });
149
+ }
150
+ function RankingsSkeleton() {
151
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("div", {
152
+ className: "flex items-center justify-between gap-2 px-6 py-3",
153
+ children: [/* @__PURE__ */ jsx(Text, {
154
+ render: /* @__PURE__ */ jsx("p", {}),
155
+ size: "3",
156
+ children: /* @__PURE__ */ jsx(Skeleton, { children: "username" })
157
+ }), /* @__PURE__ */ jsx(Text, {
158
+ render: /* @__PURE__ */ jsx("p", {}),
159
+ size: "3",
160
+ children: /* @__PURE__ */ jsx(Skeleton, { children: "0.00420 USD 11m" })
161
+ })]
162
+ }), /* @__PURE__ */ jsx(Separator, { orientation: "horizontal" })] });
163
+ }
164
+ function AuctionRankings({ className, renderBidRow }) {
165
+ const { mergedForRank, maxTotalItems, formatPrice, currencySymbol, bidValue, setBidValue, minBidValue, userBids, lockedBid, setLockedBid, showBidPreview, isAuctionEnded, cancelBidding, isBiddingActive } = useAuctionContext();
166
+ const userBidMap = useMemo(() => {
167
+ const map = /* @__PURE__ */ new Map();
168
+ for (const ub of userBids) map.set(ub.id, ub);
169
+ return map;
170
+ }, [userBids]);
171
+ const previewRef = useRef(null);
172
+ const scrollContainerRef = useRef(null);
173
+ const showPreview = useMemo(() => {
174
+ if (!showBidPreview) return false;
175
+ if (lockedBid !== null) return false;
176
+ return bidValue >= minBidValue;
177
+ }, [
178
+ showBidPreview,
179
+ bidValue,
180
+ minBidValue,
181
+ lockedBid
182
+ ]);
183
+ const previewIndex = useMemo(() => {
184
+ if (!showPreview) return 0;
185
+ const result = getProjectedRankForPrice(bidValue, mergedForRank, maxTotalItems);
186
+ return result.rank ? result.rank - 1 : 0;
187
+ }, [
188
+ showPreview,
189
+ bidValue,
190
+ mergedForRank,
191
+ maxTotalItems
192
+ ]);
193
+ const prevBiddingActiveRef = useRef(false);
194
+ useEffect(() => {
195
+ const justStartedBidding = isBiddingActive && !prevBiddingActiveRef.current;
196
+ prevBiddingActiveRef.current = isBiddingActive;
197
+ if (!showPreview) return;
198
+ const scrollToPreview = () => {
199
+ if (previewRef.current && scrollContainerRef.current) {
200
+ const container = scrollContainerRef.current;
201
+ const preview = previewRef.current;
202
+ const stickyOffset = container.querySelector("[data-ranking-group-divider]")?.offsetHeight ?? 0;
203
+ const containerRect = container.getBoundingClientRect();
204
+ const previewRect = preview.getBoundingClientRect();
205
+ const visibleTop = containerRect.top + stickyOffset;
206
+ const visibleBottom = containerRect.bottom;
207
+ const isAbove = previewRect.top < visibleTop;
208
+ const isBelow = previewRect.bottom > visibleBottom;
209
+ if (justStartedBidding || isAbove || isBelow) {
210
+ let targetScrollTop = container.scrollTop;
211
+ if (justStartedBidding) {
212
+ const visibleHeight = container.clientHeight - stickyOffset;
213
+ targetScrollTop += previewRect.top - visibleTop - (visibleHeight - previewRect.height) / 2;
214
+ } else if (isAbove) targetScrollTop += previewRect.top - visibleTop;
215
+ else if (isBelow) targetScrollTop += previewRect.bottom - visibleBottom;
216
+ container.scrollTo({
217
+ top: Math.max(0, targetScrollTop),
218
+ behavior: "auto"
219
+ });
220
+ }
221
+ }
222
+ };
223
+ const frameId = requestAnimationFrame(() => {
224
+ requestAnimationFrame(scrollToPreview);
225
+ });
226
+ return () => cancelAnimationFrame(frameId);
227
+ }, [showPreview, isBiddingActive]);
228
+ const { lockedBidId, lockedBidOriginalIndex } = useMemo(() => {
229
+ if (lockedBid === null) return {
230
+ lockedBidId: null,
231
+ lockedBidOriginalIndex: null
232
+ };
233
+ const bidId = userBids.find((ub) => ub.globalBidId === lockedBid.bidId)?.id ?? null;
234
+ return {
235
+ lockedBidId: bidId,
236
+ lockedBidOriginalIndex: bidId !== null ? mergedForRank.findIndex((b) => b.id === bidId) : null
237
+ };
238
+ }, [
239
+ lockedBid,
240
+ userBids,
241
+ mergedForRank
242
+ ]);
243
+ const allBids = useMemo(() => mergedForRank.filter((b) => b.id !== lockedBidId).map((b) => ({
244
+ id: b.id,
245
+ price: BigInt(b.price),
246
+ createdAt: new Date(b.created_at),
247
+ bidder: b.bidder ?? {
248
+ id: b.id,
249
+ name: "Unknown"
250
+ }
251
+ })), [mergedForRank, lockedBidId]);
252
+ const topUpPreviewIndex = useMemo(() => {
253
+ if (lockedBid === null || lockedBidId === null) return null;
254
+ const result = getProjectedRankForPrice(bidValue, mergedForRank.filter((b) => b.id !== lockedBidId), maxTotalItems);
255
+ return result.rank ? result.rank - 1 : 0;
256
+ }, [
257
+ lockedBid,
258
+ lockedBidId,
259
+ bidValue,
260
+ mergedForRank,
261
+ maxTotalItems
262
+ ]);
263
+ return /* @__PURE__ */ jsx("div", {
264
+ ref: scrollContainerRef,
265
+ className: cn("min-h-0 flex-1 overflow-y-auto", className),
266
+ children: /* @__PURE__ */ jsxs(Ranking.Root, {
267
+ items: allBids,
268
+ getKey: (bid) => bid.id,
269
+ boundaries: [maxTotalItems],
270
+ labels: ["Winning Bids", "Outbid"],
271
+ children: [
272
+ showPreview && /* @__PURE__ */ jsx(Ranking.Slot, {
273
+ slotKey: "preview",
274
+ atIndex: previewIndex,
275
+ children: (context) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(BidPreviewRow, {
276
+ price: bidValue,
277
+ rank: context.rank,
278
+ onCancel: cancelBidding,
279
+ formatPrice,
280
+ currencySymbol,
281
+ previewRef
282
+ }), !context.isLastInGroup && /* @__PURE__ */ jsx(Separator, { orientation: "horizontal" })] })
283
+ }),
284
+ lockedBid !== null && topUpPreviewIndex !== null && /* @__PURE__ */ jsx(Ranking.Slot, {
285
+ slotKey: "topup-preview",
286
+ atIndex: topUpPreviewIndex,
287
+ children: (context) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(TopUpPreviewRow, {
288
+ price: bidValue,
289
+ rank: context.rank,
290
+ onCancel: cancelBidding,
291
+ formatPrice,
292
+ currencySymbol
293
+ }), !context.isLastInGroup && /* @__PURE__ */ jsx(Separator, { orientation: "horizontal" })] })
294
+ }),
295
+ /* @__PURE__ */ jsx(Ranking.Empty, { children: /* @__PURE__ */ jsx(Text, {
296
+ color: "tertiary",
297
+ children: "No activity"
298
+ }) }),
299
+ /* @__PURE__ */ jsxs(Ranking.Group, { children: [/* @__PURE__ */ jsx(Ranking.GroupDivider, { className: "rounded-xl" }), /* @__PURE__ */ jsx(Ranking.GroupItem, { children: /* @__PURE__ */ jsx(Ranking.GroupItemValue, { children: (bid, context) => {
300
+ const isOutbid = context.groupIndex === 1;
301
+ const isBelowLockedBid = lockedBid !== null && lockedBidOriginalIndex !== null && lockedBidOriginalIndex >= 0 && context.globalIndex >= lockedBidOriginalIndex;
302
+ const extendedContext = {
303
+ ...context,
304
+ isOutbid
305
+ };
306
+ const userBid = userBidMap.get(bid.id);
307
+ const isUserBid = !!userBid;
308
+ const handleTopUp = () => {
309
+ if (userBid) {
310
+ setLockedBid({
311
+ bidId: userBid.globalBidId,
312
+ priceValue: userBid.price
313
+ });
314
+ setBidValue(userBid.price);
315
+ }
316
+ };
317
+ return /* @__PURE__ */ jsxs(Fragment, { children: [renderBidRow ? renderBidRow(bid, extendedContext) : /* @__PURE__ */ jsx(BidRow, {
318
+ bid,
319
+ rank: context.globalIndex + 1,
320
+ isOutbid: isOutbid || isBelowLockedBid,
321
+ isUserBid,
322
+ onTopUp: handleTopUp,
323
+ isAuctionEnded,
324
+ formatPrice,
325
+ currencySymbol
326
+ }), !context.isLastInGroup && /* @__PURE__ */ jsx(Separator, { orientation: "horizontal" })] });
327
+ } }) })] })
328
+ ]
329
+ })
330
+ });
331
+ }
332
+
333
+ //#endregion
334
+ export { AuctionRankings, RankingsSkeleton };
@@ -0,0 +1,15 @@
1
+ //#region src/components/blocks/auction/AuctionStatusTag.d.ts
2
+ interface AuctionStatusTagProps {
3
+ opensAt: Date | null;
4
+ endsAt: Date | null;
5
+ background?: "filled" | "transparent";
6
+ showCountdown?: boolean;
7
+ }
8
+ declare function AuctionStatusTag({
9
+ opensAt,
10
+ endsAt,
11
+ background,
12
+ showCountdown
13
+ }: AuctionStatusTagProps): React.ReactElement | null;
14
+ //#endregion
15
+ export { AuctionStatusTag, AuctionStatusTagProps };
@@ -0,0 +1,60 @@
1
+ "use client";
2
+
3
+ import { formatDateTime } from "../../../utils/format.js";
4
+ import { cn } from "../../../lib/cn.js";
5
+ import { Countdown } from "../../primitives/countdown/Countdown.js";
6
+ import { Text } from "../../primitives/Text.js";
7
+ import { Tag } from "../../primitives/Tag.js";
8
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
+
10
+ //#region src/components/blocks/auction/AuctionStatusTag.tsx
11
+ function getAuctionState(opensAt, endsAt) {
12
+ if (!opensAt || !endsAt) return "live";
13
+ const now = Date.now();
14
+ const open = opensAt.getTime();
15
+ const end = endsAt.getTime();
16
+ if (now < open) return "upcoming";
17
+ if (now > end) return "closed";
18
+ return "live";
19
+ }
20
+ const transparentTagClassName = "bg-transparent border-transparent p-0";
21
+ function AuctionStatusTag({ opensAt, endsAt, background = "filled", showCountdown = false }) {
22
+ const state = getAuctionState(opensAt, endsAt);
23
+ const countdownTo = state === "live" ? endsAt : state === "upcoming" ? opensAt : null;
24
+ const tagClassName = cn("inline-flex items-center gap-1.5 p-2", background === "transparent" && transparentTagClassName);
25
+ if (state === "live" && endsAt) return /* @__PURE__ */ jsxs(Tag, {
26
+ className: tagClassName,
27
+ "aria-label": "Auction is live",
28
+ children: [/* @__PURE__ */ jsxs("span", {
29
+ className: "relative flex size-2 shrink-0",
30
+ "aria-hidden": true,
31
+ children: [/* @__PURE__ */ jsx("span", { className: "absolute inline-flex size-full animate-ping rounded-full bg-success opacity-75" }), /* @__PURE__ */ jsx("span", { className: "relative inline-flex size-2 rounded-full bg-success" })]
32
+ }), /* @__PURE__ */ jsx(Text, {
33
+ size: "1",
34
+ suppressHydrationWarning: true,
35
+ children: showCountdown && countdownTo ? /* @__PURE__ */ jsxs(Fragment, { children: ["Live - ", /* @__PURE__ */ jsx(Countdown, { to: countdownTo })] }) : /* @__PURE__ */ jsxs(Fragment, { children: ["Live - Until ", formatDateTime(endsAt)] })
36
+ })]
37
+ });
38
+ if (state === "upcoming" && opensAt) return /* @__PURE__ */ jsx(Tag, {
39
+ className: tagClassName,
40
+ children: /* @__PURE__ */ jsx(Text, {
41
+ size: "1",
42
+ suppressHydrationWarning: true,
43
+ children: showCountdown && countdownTo ? /* @__PURE__ */ jsxs(Fragment, { children: ["Opens in ", /* @__PURE__ */ jsx(Countdown, { to: countdownTo })] }) : /* @__PURE__ */ jsxs(Fragment, { children: ["Opens ", formatDateTime(opensAt)] })
44
+ })
45
+ });
46
+ if (state === "closed" && endsAt) return /* @__PURE__ */ jsxs(Tag, {
47
+ className: tagClassName,
48
+ children: [/* @__PURE__ */ jsx("div", {
49
+ className: "size-2.5 shrink-0 rounded-full bg-muted-foreground",
50
+ "aria-hidden": true
51
+ }), /* @__PURE__ */ jsxs(Text, {
52
+ suppressHydrationWarning: true,
53
+ children: ["Closed - ended ", formatDateTime(endsAt)]
54
+ })]
55
+ });
56
+ return null;
57
+ }
58
+
59
+ //#endregion
60
+ export { AuctionStatusTag };
@@ -0,0 +1,38 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/components/blocks/auction/AuctionSuggestedBids.d.ts
4
+ interface SuggestedBidContextValue {
5
+ value: bigint;
6
+ display: string;
7
+ position: number;
8
+ index: number;
9
+ isSelected: boolean;
10
+ onSelect: () => void;
11
+ disabled: boolean;
12
+ projectedRank: number | null;
13
+ isWinning: boolean;
14
+ }
15
+ declare function useSuggestedBid(): SuggestedBidContextValue;
16
+ interface AuctionSuggestedBidsProps {
17
+ className?: string;
18
+ count?: number;
19
+ children: (context: SuggestedBidContextValue) => React.ReactNode;
20
+ }
21
+ declare function AuctionSuggestedBidsRoot({
22
+ className,
23
+ count,
24
+ children
25
+ }: AuctionSuggestedBidsProps): React.ReactElement | null;
26
+ interface AuctionSuggestedBidsItemProps {
27
+ labels?: string[];
28
+ }
29
+ declare function AuctionSuggestedBidsItem({
30
+ labels
31
+ }: AuctionSuggestedBidsItemProps): React.ReactElement;
32
+ interface AuctionSuggestedBidsComponent {
33
+ Root: typeof AuctionSuggestedBidsRoot;
34
+ Item: typeof AuctionSuggestedBidsItem;
35
+ }
36
+ declare const AuctionSuggestedBids: AuctionSuggestedBidsComponent;
37
+ //#endregion
38
+ export { AuctionSuggestedBids, AuctionSuggestedBidsProps, SuggestedBidContextValue, useSuggestedBid };