@m3000/market 0.0.1 → 0.0.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 (79) hide show
  1. package/README.md +93 -0
  2. package/dist/styles.css +2 -0
  3. package/{src/styles/index.css → dist/theme.css} +0 -1
  4. package/package.json +10 -10
  5. package/src/components/blocks/auction/Auction.tsx +0 -74
  6. package/src/components/blocks/auction/AuctionArtwork.tsx +0 -4
  7. package/src/components/blocks/auction/AuctionBidForm.tsx +0 -138
  8. package/src/components/blocks/auction/AuctionBidInput.tsx +0 -166
  9. package/src/components/blocks/auction/AuctionContext.tsx +0 -401
  10. package/src/components/blocks/auction/AuctionInfo.tsx +0 -36
  11. package/src/components/blocks/auction/AuctionLayout.tsx +0 -200
  12. package/src/components/blocks/auction/AuctionRankings.tsx +0 -435
  13. package/src/components/blocks/auction/AuctionStatusTag.tsx +0 -98
  14. package/src/components/blocks/auction/AuctionSuggestedBids.tsx +0 -203
  15. package/src/components/blocks/auction/AuctionYourBidCard.tsx +0 -125
  16. package/src/components/blocks/auction/AuctionYourBids.tsx +0 -61
  17. package/src/components/blocks/auction/index.ts +0 -42
  18. package/src/components/blocks/index.ts +0 -1
  19. package/src/components/index.ts +0 -2
  20. package/src/components/primitives/Button.tsx +0 -183
  21. package/src/components/primitives/Drawer.tsx +0 -125
  22. package/src/components/primitives/Feedback.tsx +0 -185
  23. package/src/components/primitives/MorphDialog.tsx +0 -160
  24. package/src/components/primitives/Price.tsx +0 -394
  25. package/src/components/primitives/PriceInput.tsx +0 -48
  26. package/src/components/primitives/Receipt.tsx +0 -711
  27. package/src/components/primitives/Scale.tsx +0 -287
  28. package/src/components/primitives/Separator.tsx +0 -87
  29. package/src/components/primitives/Skeleton.tsx +0 -33
  30. package/src/components/primitives/SteppedInput.tsx +0 -313
  31. package/src/components/primitives/Tabs.tsx +0 -161
  32. package/src/components/primitives/Tag.tsx +0 -48
  33. package/src/components/primitives/Text.tsx +0 -102
  34. package/src/components/primitives/countdown/Countdown.tsx +0 -43
  35. package/src/components/primitives/countdown/index.ts +0 -2
  36. package/src/components/primitives/framed-image/FramedImage.tsx +0 -51
  37. package/src/components/primitives/framed-image/index.ts +0 -1
  38. package/src/components/primitives/index.ts +0 -42
  39. package/src/components/primitives/ranked-list/RankedList.tsx +0 -9
  40. package/src/components/primitives/ranked-list/Ranking.tsx +0 -454
  41. package/src/components/primitives/ranked-list/index.ts +0 -8
  42. package/src/hooks/index.ts +0 -1
  43. package/src/hooks/useCountdown.ts +0 -91
  44. package/src/index.ts +0 -130
  45. package/src/lib/cn.ts +0 -81
  46. package/src/lib/index.ts +0 -2
  47. package/src/lib/motion.ts +0 -55
  48. package/src/public/lea-83-time-walk.png +0 -0
  49. package/src/public/lea-83-time-walk.webp +0 -0
  50. package/src/stories/Auction.stories.tsx +0 -658
  51. package/src/stories/AuctionLayout.stories.tsx +0 -313
  52. package/src/stories/AuctionStatusTag.stories.tsx +0 -166
  53. package/src/stories/AuctionYourBidCard.stories.tsx +0 -257
  54. package/src/stories/Button.stories.tsx +0 -306
  55. package/src/stories/Countdown.stories.tsx +0 -158
  56. package/src/stories/Feedback.stories.tsx +0 -80
  57. package/src/stories/FramedImage.stories.tsx +0 -46
  58. package/src/stories/MorphDialog.stories.tsx +0 -88
  59. package/src/stories/Price.stories.tsx +0 -292
  60. package/src/stories/RankedList.stories.tsx +0 -190
  61. package/src/stories/Receipt.stories.tsx +0 -221
  62. package/src/stories/Scale.stories.tsx +0 -578
  63. package/src/stories/Separator.stories.tsx +0 -188
  64. package/src/stories/Skeleton.stories.tsx +0 -138
  65. package/src/stories/SteppedInput.stories.tsx +0 -321
  66. package/src/stories/Tabs.stories.tsx +0 -215
  67. package/src/stories/Tag.stories.tsx +0 -138
  68. package/src/stories/Text.stories.tsx +0 -245
  69. package/src/types/index.ts +0 -149
  70. package/src/utils/format.ts +0 -130
  71. package/src/utils/index.ts +0 -16
  72. package/src/utils/rank-utils.ts +0 -131
  73. package/src/utils/tick-validation.ts +0 -65
  74. /package/{src/styles → dist}/globals.css +0 -0
  75. /package/{src/styles → dist}/theme/animation.css +0 -0
  76. /package/{src/styles → dist}/theme/color.css +0 -0
  77. /package/{src/styles → dist}/theme/index.css +0 -0
  78. /package/{src/styles → dist}/theme/typography.css +0 -0
  79. /package/{src/styles → dist}/utility.css +0 -0
@@ -1,401 +0,0 @@
1
- "use client";
2
-
3
- import {
4
- createContext,
5
- useCallback,
6
- useContext,
7
- useMemo,
8
- useState,
9
- } from "react";
10
- import type {
11
- AuctionData,
12
- AuctionFormatters,
13
- AuctionTickConfig,
14
- AuctionUserBid,
15
- OperationState,
16
- RankableBid,
17
- } from "@/types";
18
- import { getProjectedRankForPrice, getSuggestedBidPrices } from "@/utils";
19
-
20
- export interface AuctionContextValue {
21
- auction: AuctionData;
22
- isAuctionEnded: boolean;
23
-
24
- bids: RankableBid[];
25
- userBids: AuctionUserBid[];
26
- maxTotalItems: number;
27
-
28
- bidValue: bigint;
29
- setBidValue: (value: bigint | ((prev: bigint) => bigint)) => void;
30
-
31
- minBidValue: bigint;
32
- reservePriceValue: bigint;
33
- tickReferencePrice: bigint;
34
- tickConfig: AuctionTickConfig | undefined;
35
- tickSize: bigint;
36
-
37
- placeBidOperation: OperationState;
38
- topUpOperation: OperationState;
39
-
40
- lockedBid: { bidId: bigint; priceValue: bigint } | null;
41
-
42
- mergedForRank: RankableBid[];
43
- getRankForBid: (bidId: string) => number | null;
44
- getProjectedRank: (priceValue: bigint) => {
45
- rank: number | null;
46
- isWinning: boolean;
47
- };
48
- getSuggestedBids: () => bigint[];
49
-
50
- showBidPreview: boolean;
51
- setShowBidPreview: (show: boolean) => void;
52
-
53
- isBiddingActive: boolean;
54
- setIsBiddingActive: (active: boolean) => void;
55
- startBidding: () => void;
56
- cancelBidding: () => void;
57
-
58
- setLockedBid: (bid: { bidId: bigint; priceValue: bigint } | null) => void;
59
- handlePlaceBid: (price: string) => Promise<boolean>;
60
- handleTopUp: (newPrice: string) => Promise<boolean>;
61
- handleClaimEdition?: (bidId: string) => Promise<boolean>;
62
- resetOperations: () => void;
63
-
64
- formatPrice: (priceValue: bigint) => string;
65
- formatTime: (date: Date) => string;
66
- currencySymbol: string;
67
- inputDecimals: number;
68
- }
69
-
70
- export const AuctionContext: React.Context<AuctionContextValue | null> =
71
- createContext<AuctionContextValue | null>(null);
72
-
73
- export function useAuctionContext(): AuctionContextValue {
74
- const ctx = useContext(AuctionContext);
75
- if (!ctx) {
76
- throw new Error(
77
- "useAuctionContext must be used within an Auction provider",
78
- );
79
- }
80
- return ctx;
81
- }
82
-
83
- export interface AuctionProviderProps {
84
- auction: AuctionData;
85
- bids: RankableBid[];
86
- userBids: AuctionUserBid[];
87
- onPlaceBid: (price: bigint, quantity: bigint) => Promise<boolean>;
88
- onTopUpBid: (
89
- bidId: bigint,
90
- newPrice: bigint,
91
- additionalValue: bigint,
92
- ) => Promise<boolean>;
93
- onClaimEdition?: (bidId: string) => Promise<boolean>;
94
- formatters?: AuctionFormatters;
95
- children: React.ReactNode;
96
- }
97
-
98
- export function AuctionProvider({
99
- auction,
100
- bids,
101
- userBids,
102
- onPlaceBid,
103
- onTopUpBid,
104
- onClaimEdition,
105
- formatters,
106
- children,
107
- }: AuctionProviderProps): React.ReactElement {
108
- const defaultFormatPrice = (priceValue: bigint) => {
109
- const val = Number(priceValue) / 1e18;
110
- return val.toLocaleString("en-US", {
111
- minimumFractionDigits: 3,
112
- maximumFractionDigits: 3,
113
- });
114
- };
115
- const defaultFormatTime = (date: Date) => {
116
- const now = Date.now();
117
- const diff = date.getTime() - now;
118
- const isPast = diff < 0;
119
- const absMs = Math.abs(diff);
120
- const seconds = Math.floor(absMs / 1000);
121
- const minutes = Math.floor(seconds / 60);
122
- const hours = Math.floor(minutes / 60);
123
- const days = Math.floor(hours / 24);
124
-
125
- if (days > 0) return `${days}d ${hours % 24}h ${isPast ? "ago" : ""}`;
126
- if (hours > 0) return `${hours}h ${minutes % 60}m ${isPast ? "ago" : ""}`;
127
- if (minutes > 0)
128
- return `${minutes}m ${seconds % 60}s ${isPast ? "ago" : ""}`;
129
- return `${seconds}s ${isPast ? "ago" : ""}`;
130
- };
131
-
132
- const formatPrice = formatters?.formatPrice ?? defaultFormatPrice;
133
- const formatTime = formatters?.formatTime ?? defaultFormatTime;
134
- const currencySymbol = formatters?.currencySymbol ?? "USD";
135
- const inputDecimals = formatters?.inputDecimals ?? 18;
136
-
137
- const isAuctionEnded = auction.endsAt
138
- ? Date.now() > auction.endsAt.getTime()
139
- : false;
140
-
141
- const reservePriceValue = auction.reservePrice;
142
- const tickConfig = auction.tickConfig;
143
-
144
- const activeBids = bids.filter((b) => {
145
- const bid = userBids.find((ub) => ub.id === b.id);
146
- return !bid || bid.status === "active";
147
- });
148
-
149
- const totalActiveQty = BigInt(activeBids.length);
150
-
151
- const mergedForRank = useMemo(() => {
152
- const cutoffIds = new Set(bids.map((b) => b.id));
153
-
154
- const myActiveBids = userBids.filter(
155
- (bid) => bid.status === "active" && !cutoffIds.has(bid.id),
156
- );
157
-
158
- const myBidsNotInCutoff: RankableBid[] = myActiveBids.map((bid) => ({
159
- id: bid.id,
160
- price: bid.price.toString(),
161
- created_at: bid.createdAt.toISOString(),
162
- }));
163
-
164
- const merged: RankableBid[] = [...bids, ...myBidsNotInCutoff];
165
-
166
- return merged.sort((a, b) => {
167
- const pa = BigInt(a.price);
168
- const pb = BigInt(b.price);
169
- if (pa !== pb) return pb > pa ? 1 : -1;
170
- return (
171
- new Date(a.created_at).getTime() - new Date(b.created_at).getTime()
172
- );
173
- });
174
- }, [bids, userBids]);
175
-
176
- const minBidValue = useMemo(() => {
177
- if (totalActiveQty >= BigInt(auction.maxTotalItems)) {
178
- const winningBids = mergedForRank.slice(0, auction.maxTotalItems);
179
-
180
- if (winningBids.length > 0) {
181
- const lastWinning = winningBids[winningBids.length - 1];
182
- const tickSize = tickConfig
183
- ? BigInt(lastWinning.price) > tickConfig.threshold
184
- ? tickConfig.largeTickSize
185
- : tickConfig.smallTickSize
186
- : BigInt(lastWinning.price);
187
- return BigInt(lastWinning.price) + tickSize;
188
- }
189
- }
190
- return reservePriceValue;
191
- }, [
192
- reservePriceValue,
193
- totalActiveQty,
194
- auction.maxTotalItems,
195
- mergedForRank,
196
- tickConfig,
197
- ]);
198
-
199
- const tickReferencePrice = minBidValue;
200
-
201
- const tickSize = useMemo(() => {
202
- if (!tickConfig) return minBidValue;
203
- return BigInt(minBidValue) > tickConfig.threshold
204
- ? tickConfig.largeTickSize
205
- : tickConfig.smallTickSize;
206
- }, [tickConfig, minBidValue]);
207
-
208
- const getRankForBid = useCallback(
209
- (bidId: string) => {
210
- const idx = mergedForRank.findIndex((b) => b.id === bidId);
211
- return idx >= 0 ? idx + 1 : null;
212
- },
213
- [mergedForRank],
214
- );
215
-
216
- const getProjectedRank = useCallback(
217
- (priceValue: bigint) => {
218
- return getProjectedRankForPrice(
219
- priceValue,
220
- mergedForRank,
221
- auction.maxTotalItems,
222
- );
223
- },
224
- [mergedForRank, auction.maxTotalItems],
225
- );
226
-
227
- const getSuggestedBids = useCallback(() => {
228
- return getSuggestedBidPrices({
229
- mergedForRank,
230
- maxTotalItems: auction.maxTotalItems,
231
- minBidValue,
232
- reservePriceValue,
233
- tickConfig,
234
- tickSize,
235
- });
236
- }, [
237
- mergedForRank,
238
- auction.maxTotalItems,
239
- minBidValue,
240
- reservePriceValue,
241
- tickConfig,
242
- tickSize,
243
- ]);
244
-
245
- const [placeBidOperation, setPlaceBidOperation] = useState<OperationState>({
246
- status: "idle",
247
- });
248
- const [topUpOperation, setTopUpOperation] = useState<OperationState>({
249
- status: "idle",
250
- });
251
-
252
- const [lockedBid, setLockedBid] = useState<{
253
- bidId: bigint;
254
- priceValue: bigint;
255
- } | null>(null);
256
-
257
- const [showBidPreview, setShowBidPreview] = useState(false);
258
-
259
- const [isBiddingActive, setIsBiddingActive] = useState(false);
260
-
261
- const startBidding = useCallback(() => {
262
- setIsBiddingActive(true);
263
- setShowBidPreview(true);
264
- }, []);
265
-
266
- const cancelBidding = useCallback(() => {
267
- setIsBiddingActive(false);
268
- setShowBidPreview(false);
269
- setLockedBid(null);
270
- }, []);
271
-
272
- const setLockedBidAndActivate = useCallback(
273
- (bid: { bidId: bigint; priceValue: bigint } | null) => {
274
- setLockedBid(bid);
275
- if (bid !== null) {
276
- setIsBiddingActive(true);
277
- setShowBidPreview(true);
278
- }
279
- },
280
- [],
281
- );
282
-
283
- const [bidValue, setBidValue] = useState<bigint>(minBidValue);
284
-
285
- const resetOperations = useCallback(() => {
286
- setPlaceBidOperation({ status: "idle" });
287
- setTopUpOperation({ status: "idle" });
288
- }, []);
289
-
290
- const handlePlaceBid = useCallback(
291
- async (price: string) => {
292
- const priceValue = BigInt(price);
293
- setPlaceBidOperation({ status: "pending" });
294
-
295
- try {
296
- const success = await onPlaceBid(priceValue, 1n);
297
- if (success) {
298
- setPlaceBidOperation({ status: "success" });
299
- setShowBidPreview(false);
300
- return true;
301
- } else {
302
- setPlaceBidOperation({
303
- status: "error",
304
- error: "Transaction failed",
305
- });
306
- return false;
307
- }
308
- } catch (err) {
309
- setPlaceBidOperation({
310
- status: "error",
311
- error: err instanceof Error ? err.message : "Unknown error",
312
- });
313
- return false;
314
- }
315
- },
316
- [onPlaceBid],
317
- );
318
-
319
- const handleTopUp = useCallback(
320
- async (newPrice: string) => {
321
- if (!lockedBid) return false;
322
-
323
- const newPriceValue = BigInt(newPrice);
324
- const additionalValue = newPriceValue - lockedBid.priceValue;
325
-
326
- setTopUpOperation({ status: "pending" });
327
-
328
- try {
329
- const success = await onTopUpBid(
330
- lockedBid.bidId,
331
- newPriceValue,
332
- additionalValue,
333
- );
334
- if (success) {
335
- setTopUpOperation({ status: "success" });
336
- setLockedBid(null);
337
- return true;
338
- } else {
339
- setTopUpOperation({ status: "error", error: "Transaction failed" });
340
- return false;
341
- }
342
- } catch (err) {
343
- setTopUpOperation({
344
- status: "error",
345
- error: err instanceof Error ? err.message : "Unknown error",
346
- });
347
- return false;
348
- }
349
- },
350
- [lockedBid, onTopUpBid],
351
- );
352
-
353
- const handleClaimEdition = useCallback(
354
- async (bidId: string) => {
355
- if (!onClaimEdition) return false;
356
- return onClaimEdition(bidId);
357
- },
358
- [onClaimEdition],
359
- );
360
-
361
- const value: AuctionContextValue = {
362
- auction,
363
- isAuctionEnded,
364
- bids,
365
- userBids,
366
- maxTotalItems: auction.maxTotalItems,
367
- bidValue,
368
- setBidValue,
369
- minBidValue,
370
- reservePriceValue,
371
- tickReferencePrice,
372
- tickConfig,
373
- tickSize,
374
- placeBidOperation,
375
- topUpOperation,
376
- lockedBid,
377
- mergedForRank,
378
- getRankForBid,
379
- getProjectedRank,
380
- getSuggestedBids,
381
- showBidPreview,
382
- setShowBidPreview,
383
- isBiddingActive,
384
- setIsBiddingActive,
385
- startBidding,
386
- cancelBidding,
387
- setLockedBid: setLockedBidAndActivate,
388
- handlePlaceBid,
389
- handleTopUp,
390
- handleClaimEdition,
391
- resetOperations,
392
- formatPrice,
393
- formatTime,
394
- currencySymbol,
395
- inputDecimals,
396
- };
397
-
398
- return (
399
- <AuctionContext.Provider value={value}>{children}</AuctionContext.Provider>
400
- );
401
- }
@@ -1,36 +0,0 @@
1
- "use client";
2
-
3
- import { Text } from "@/components/primitives";
4
- import { useAuctionContext } from "./AuctionContext";
5
- import { AuctionStatusTag } from "./AuctionStatusTag";
6
-
7
- export interface AuctionInfoProps {
8
- className?: string;
9
- }
10
-
11
- export function AuctionInfo({
12
- className,
13
- }: AuctionInfoProps): React.ReactElement {
14
- const { auction, isAuctionEnded, maxTotalItems } = useAuctionContext();
15
-
16
- const editionsLabel =
17
- maxTotalItems === 1 ? "1 item" : `${maxTotalItems} items`;
18
-
19
- return (
20
- <div className={className}>
21
- <div className="flex flex-wrap items-center gap-2">
22
- <AuctionStatusTag
23
- opensAt={auction.opensAt}
24
- endsAt={auction.endsAt}
25
- background="transparent"
26
- />
27
- </div>
28
- {!isAuctionEnded ? (
29
- <Text size="2" color="tertiary" className="mt-2">
30
- Bid on one of {editionsLabel}. Top {maxTotalItems} bidders win and pay
31
- the lowest winning bid.
32
- </Text>
33
- ) : null}
34
- </div>
35
- );
36
- }
@@ -1,200 +0,0 @@
1
- "use client";
2
-
3
- import type { ReactNode } from "react";
4
- import { Button } from "@/components/primitives";
5
- import { cn } from "@/lib";
6
- import { useAuctionContext } from "./AuctionContext";
7
-
8
- export interface AuctionLayoutProps {
9
- children: ReactNode;
10
- className?: string;
11
- height?: string | number;
12
- }
13
-
14
- export function AuctionLayout({
15
- children,
16
- className,
17
- height = "calc(100vh - 4rem)",
18
- }: AuctionLayoutProps): React.ReactElement {
19
- const heightStyle = typeof height === "number" ? `${height}px` : height;
20
- const { isBiddingActive } = useAuctionContext();
21
-
22
- return (
23
- <div
24
- className={cn(
25
- "relative grid overflow-hidden grid-rows-[minmax(0,1fr)_minmax(0,1fr)]",
26
- isBiddingActive && "grid-rows-1",
27
- "lg:grid-cols-2 lg:grid-rows-1",
28
- className,
29
- )}
30
- style={{ height: heightStyle }}
31
- >
32
- {children}
33
- </div>
34
- );
35
- }
36
-
37
- export interface AuctionDetailsProps {
38
- children: ReactNode;
39
- className?: string;
40
- }
41
-
42
- export function AuctionDetails({
43
- children,
44
- className,
45
- }: AuctionDetailsProps): React.ReactElement {
46
- const { isBiddingActive } = useAuctionContext();
47
-
48
- return (
49
- <div
50
- className={cn(
51
- "relative flex h-full min-h-0 flex-col overflow-hidden",
52
- "border-border",
53
- "lg:border-r",
54
- isBiddingActive && "overflow-hidden",
55
- className,
56
- )}
57
- >
58
- {children}
59
- </div>
60
- );
61
- }
62
-
63
- export interface AuctionDetailsHeaderProps {
64
- children: ReactNode;
65
- className?: string;
66
- }
67
-
68
- export function AuctionDetailsHeader({
69
- children,
70
- className,
71
- }: AuctionDetailsHeaderProps): React.ReactElement {
72
- const { isBiddingActive } = useAuctionContext();
73
-
74
- return (
75
- <div
76
- className={cn(
77
- "flex min-h-0 grow flex-col p-6",
78
- isBiddingActive &&
79
- [
80
- "max-lg:overflow-hidden",
81
- "max-lg:[&>*:nth-child(n+3):not(:last-child)]:hidden",
82
- "max-lg:[&>*:last-child]:pointer-events-none",
83
- "max-lg:[&>*:last-child]:absolute",
84
- "max-lg:[&>*:last-child]:inset-x-6",
85
- "max-lg:[&>*:last-child]:bottom-6",
86
- "max-lg:[&>*:last-child]:top-28",
87
- "max-lg:[&>*:last-child]:min-h-0",
88
- "max-lg:[&>*:last-child]:overflow-hidden",
89
- ].join(" "),
90
- className,
91
- )}
92
- >
93
- {children}
94
- </div>
95
- );
96
- }
97
-
98
- export interface AuctionDetailsBodyProps {
99
- children: ReactNode;
100
- className?: string;
101
- }
102
-
103
- export function AuctionDetailsBody({
104
- children,
105
- className,
106
- }: AuctionDetailsBodyProps): React.ReactElement {
107
- return (
108
- <div
109
- className={cn(
110
- "hidden p-6 lg:block lg:min-h-0 lg:flex-1 lg:overflow-y-auto",
111
- className,
112
- )}
113
- >
114
- {children}
115
- </div>
116
- );
117
- }
118
-
119
- export interface AuctionDetailsFooterProps {
120
- children: ReactNode;
121
- className?: string;
122
- }
123
-
124
- export function AuctionDetailsFooter({
125
- children,
126
- className,
127
- }: AuctionDetailsFooterProps): React.ReactElement {
128
- return (
129
- <div
130
- className={cn("mt-auto shrink-0 border-t border-border p-6", className)}
131
- >
132
- {children}
133
- </div>
134
- );
135
- }
136
-
137
- export interface AuctionRankingsContainerProps {
138
- children: ReactNode;
139
- className?: string;
140
- }
141
-
142
- export function AuctionRankingsContainer({
143
- children,
144
- className,
145
- }: AuctionRankingsContainerProps): React.ReactElement {
146
- const { isBiddingActive } = useAuctionContext();
147
-
148
- return (
149
- <div
150
- className={cn(
151
- "grid h-full min-h-0 grid-rows-[minmax(0,1fr)_auto]",
152
- isBiddingActive &&
153
- "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",
154
- className,
155
- )}
156
- >
157
- {children}
158
- </div>
159
- );
160
- }
161
-
162
- export interface AuctionBiddingPanelProps {
163
- children: ReactNode;
164
- className?: string;
165
- }
166
-
167
- export function AuctionBiddingPanel({
168
- children,
169
- className,
170
- }: AuctionBiddingPanelProps): React.ReactElement {
171
- const { isBiddingActive, startBidding, isAuctionEnded, setShowBidPreview } =
172
- useAuctionContext();
173
-
174
- const handleStartBidding = () => {
175
- startBidding();
176
- setShowBidPreview(true);
177
- };
178
-
179
- return (
180
- <div
181
- className={cn(
182
- "row-start-2 rounded-t-[1.75rem] border-t border-border bg-background p-6 lg:rounded-xl",
183
- className,
184
- )}
185
- >
186
- {!isBiddingActive ? (
187
- <Button
188
- className="w-full"
189
- size="lg"
190
- disabled={isAuctionEnded}
191
- onClick={handleStartBidding}
192
- >
193
- {isAuctionEnded ? "Auction Ended" : "Start Bidding"}
194
- </Button>
195
- ) : (
196
- children
197
- )}
198
- </div>
199
- );
200
- }