@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,190 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { useMemo, useState } from "react";
3
+ import { Ranking } from "@/components";
4
+ import { Separator, Text } from "@/components/primitives";
5
+
6
+ interface Player {
7
+ id: string;
8
+ name: string;
9
+ score: number;
10
+ }
11
+
12
+ const players: Player[] = [
13
+ { id: "1", name: "Alice", score: 950 },
14
+ { id: "2", name: "Bob", score: 880 },
15
+ { id: "3", name: "Charlie", score: 820 },
16
+ { id: "4", name: "Diana", score: 790 },
17
+ { id: "5", name: "Eve", score: 750 },
18
+ ];
19
+
20
+ const meta: Meta<typeof Ranking.Root> = {
21
+ title: "Primitives/Ranking",
22
+ component: Ranking.Root,
23
+ parameters: {
24
+ layout: "centered",
25
+ },
26
+ decorators: [
27
+ (Story) => (
28
+ <div className="h-125 w-96 overflow-y-auto rounded-lg border border-border bg-background">
29
+ <Story />
30
+ </div>
31
+ ),
32
+ ],
33
+ };
34
+
35
+ export default meta;
36
+
37
+ function RankingRows() {
38
+ return (
39
+ <Ranking.Group>
40
+ <Ranking.GroupDivider />
41
+ <Ranking.GroupItem>
42
+ <Ranking.GroupItemValue>
43
+ {(player: Player, context) => (
44
+ <>
45
+ <div className="flex items-center justify-between px-4 py-3">
46
+ <div className="flex items-center gap-3">
47
+ <Ranking.GroupItemIndex />
48
+ <Text>{player.name}</Text>
49
+ </div>
50
+ <Text color="secondary">{player.score} pts</Text>
51
+ </div>
52
+ {!context.isLastInGroup && <Separator orientation="horizontal" />}
53
+ </>
54
+ )}
55
+ </Ranking.GroupItemValue>
56
+ </Ranking.GroupItem>
57
+ </Ranking.Group>
58
+ );
59
+ }
60
+
61
+ export const Basic: StoryObj<typeof Ranking.Root> = {
62
+ render: () => (
63
+ <Ranking.Root
64
+ items={players}
65
+ getKey={(player) => player.id}
66
+ boundaries={[3]}
67
+ labels={["Top 3", "Others"]}
68
+ >
69
+ <Ranking.Empty>
70
+ <Text color="tertiary">No players</Text>
71
+ </Ranking.Empty>
72
+ <RankingRows />
73
+ </Ranking.Root>
74
+ ),
75
+ };
76
+
77
+ export const CustomGroup: StoryObj<typeof Ranking.Root> = {
78
+ render: () => (
79
+ <Ranking.Root
80
+ items={players}
81
+ getKey={(player) => player.id}
82
+ boundaries={[2]}
83
+ labels={["Qualified", "Chasing"]}
84
+ >
85
+ <Ranking.Group>
86
+ <Ranking.GroupDivider className="px-3 py-2">
87
+ {({ label, groupIndex }) => (
88
+ <div className="flex items-center justify-between rounded-md bg-muted px-3 py-2">
89
+ <Text weight="medium">{label}</Text>
90
+ <Text color="secondary">
91
+ {groupIndex === 0 ? "In form" : "Needs a result"}
92
+ </Text>
93
+ </div>
94
+ )}
95
+ </Ranking.GroupDivider>
96
+ <Ranking.GroupItem>
97
+ <Ranking.GroupItemValue>
98
+ {(player: Player, context) => (
99
+ <>
100
+ <div className="flex items-center justify-between px-4 py-3">
101
+ <div className="flex items-center gap-3">
102
+ <Ranking.GroupItemIndex />
103
+ <Text>{player.name}</Text>
104
+ </div>
105
+ <Text color="secondary">{player.score} pts</Text>
106
+ </div>
107
+ {!context.isLastInGroup && (
108
+ <Separator orientation="horizontal" />
109
+ )}
110
+ </>
111
+ )}
112
+ </Ranking.GroupItemValue>
113
+ </Ranking.GroupItem>
114
+ </Ranking.Group>
115
+ </Ranking.Root>
116
+ ),
117
+ };
118
+
119
+ export const StaticSlot: StoryObj<typeof Ranking.Root> = {
120
+ render: () => (
121
+ <Ranking.Root
122
+ items={players}
123
+ getKey={(player) => player.id}
124
+ boundaries={[3]}
125
+ labels={["Top 3", "Others"]}
126
+ >
127
+ <Ranking.Slot slotKey="reserved" atIndex={1}>
128
+ <div className="mx-4 my-3 rounded-md border border-dashed border-border bg-muted px-3 py-2">
129
+ <Text size="2" weight="medium">
130
+ Reserved position
131
+ </Text>
132
+ <Text size="2" color="secondary">
133
+ Static slot content can be inserted at a fixed ranked index.
134
+ </Text>
135
+ </div>
136
+ </Ranking.Slot>
137
+ <RankingRows />
138
+ </Ranking.Root>
139
+ ),
140
+ };
141
+
142
+ export const DynamicSlot: StoryObj<typeof Ranking.Root> = {
143
+ render: () => {
144
+ const [candidateScore, setCandidateScore] = useState(905);
145
+ const insertionIndex = useMemo(() => {
146
+ const index = players.findIndex(
147
+ (player) => candidateScore >= player.score,
148
+ );
149
+ return index === -1 ? players.length : index;
150
+ }, [candidateScore]);
151
+
152
+ return (
153
+ <div className="flex flex-col">
154
+ <div className="flex flex-wrap gap-2 border-b border-border p-3">
155
+ {[975, 905, 845, 760].map((score) => (
156
+ <button
157
+ key={score}
158
+ type="button"
159
+ onClick={() => setCandidateScore(score)}
160
+ className="rounded-md border border-border px-2.5 py-1 text-sm"
161
+ >
162
+ Preview {score}
163
+ </button>
164
+ ))}
165
+ </div>
166
+ <Ranking.Root
167
+ items={players}
168
+ getKey={(player) => player.id}
169
+ boundaries={[3]}
170
+ labels={["Podium", "Field"]}
171
+ >
172
+ <Ranking.Slot slotKey="preview" atIndex={insertionIndex}>
173
+ {({ rank, groupIndex }) => (
174
+ <div className="mx-4 my-3 rounded-md border border-emerald-500/40 bg-emerald-500/10 px-3 py-2">
175
+ <Text size="2" weight="medium">
176
+ Candidate preview
177
+ </Text>
178
+ <Text size="2" color="secondary">
179
+ Score {candidateScore} would render at rank #{rank} in group{" "}
180
+ {groupIndex + 1}.
181
+ </Text>
182
+ </div>
183
+ )}
184
+ </Ranking.Slot>
185
+ <RankingRows />
186
+ </Ranking.Root>
187
+ </div>
188
+ );
189
+ },
190
+ };
@@ -0,0 +1,221 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Price, Receipt } from "@/components/primitives";
3
+
4
+ const meta: Meta<typeof Receipt> = {
5
+ title: "Primitives/Receipt",
6
+ component: Receipt,
7
+ parameters: {
8
+ layout: "centered",
9
+ },
10
+ decorators: [
11
+ (Story) => (
12
+ <div className="flex flex-col items-center gap-4 p-8 tabular-nums">
13
+ <Story />
14
+ </div>
15
+ ),
16
+ ],
17
+ };
18
+
19
+ export default meta;
20
+
21
+ export const Basic: StoryObj<typeof Receipt> = {
22
+ render: () => (
23
+ <div className="bg-surface w-80 rounded-lg border border-border p-4">
24
+ <Receipt decimals={2}>
25
+ <Receipt.Price maxDecimals={2}>
26
+ <Price.Symbol>$</Price.Symbol>
27
+ <Price.Value />
28
+ </Receipt.Price>
29
+ <Receipt.Header>
30
+ <span className="text-xl font-semibold">Order Summary</span>
31
+ </Receipt.Header>
32
+ <Receipt.Item label="Item 1" value={1511n} />
33
+ <Receipt.Item label="Item 2" value={2000n} />
34
+ <Receipt.Item label="Item 3" value={500n} />
35
+ <Receipt.Subtotal />
36
+ <Receipt.Tax rate={0.1} />
37
+ <Receipt.Separator />
38
+ <Receipt.Total />
39
+ </Receipt>
40
+ </div>
41
+ ),
42
+ };
43
+
44
+ export const WithSubtotal: StoryObj<typeof Receipt> = {
45
+ render: () => (
46
+ <div className="bg-surface w-80 rounded-lg border border-border p-4">
47
+ <Receipt decimals={6}>
48
+ <Receipt.Price maxDecimals={2}>
49
+ <Price.Symbol>$</Price.Symbol>
50
+ <Price.Value />
51
+ </Receipt.Price>
52
+ <Receipt.Header>
53
+ <span className="text-xl font-semibold">Order Summary</span>
54
+ </Receipt.Header>
55
+ <Receipt.Item label="Item 1" value={1500000n} />
56
+ <Receipt.Item label="Item 2" value={2000000n} />
57
+ <Receipt.Item label="Item 3" value={500000n} />
58
+ <Receipt.Separator />
59
+ <Receipt.Subtotal />
60
+ <Receipt.Total />
61
+ </Receipt>
62
+ </div>
63
+ ),
64
+ };
65
+
66
+ export const WithDiscount: StoryObj<typeof Receipt> = {
67
+ render: () => (
68
+ <div className="bg-surface w-80 rounded-lg border border-border p-4">
69
+ <Receipt decimals={6}>
70
+ <Receipt.Price maxDecimals={2}>
71
+ <Price.Symbol>$</Price.Symbol>
72
+ <Price.Value />
73
+ </Receipt.Price>
74
+ <Receipt.Header>
75
+ <span className="text-xl font-semibold">Order Summary</span>
76
+ </Receipt.Header>
77
+ <Receipt.Item label="Item 1" value={1500000n} />
78
+ <Receipt.Item label="Item 2" value={2000000n} />
79
+ <Receipt.Separator />
80
+ <Receipt.Subtotal />
81
+ <Receipt.Discount label="Promo Code" value={500000n} />
82
+ <Receipt.Total />
83
+ </Receipt>
84
+ </div>
85
+ ),
86
+ };
87
+
88
+ export const WithTax: StoryObj<typeof Receipt> = {
89
+ render: () => (
90
+ <div className="bg-surface w-80 rounded-lg border border-border p-4">
91
+ <Receipt decimals={2}>
92
+ <Receipt.Price maxDecimals={2}>
93
+ <Price.Symbol>$</Price.Symbol>
94
+ <Price.Value />
95
+ </Receipt.Price>
96
+ <Receipt.Header>
97
+ <span className="text-xl font-semibold">Receipt</span>
98
+ </Receipt.Header>
99
+ <Receipt.Item label="Subtotal" value={4000} />
100
+ <Receipt.Tax rate={0.08} />
101
+ <Receipt.Total />
102
+ </Receipt>
103
+ </div>
104
+ ),
105
+ };
106
+
107
+ export const WithFee: StoryObj<typeof Receipt> = {
108
+ render: () => (
109
+ <div className="bg-surface w-80 rounded-lg border border-border p-4">
110
+ <Receipt decimals={6}>
111
+ <Receipt.Price maxDecimals={2}>
112
+ <Price.Symbol>$</Price.Symbol>
113
+ <Price.Value />
114
+ </Receipt.Price>
115
+ <Receipt.Header>
116
+ <span className="text-xl font-semibold">Order Summary</span>
117
+ </Receipt.Header>
118
+ <Receipt.Item label="Item 1" value={1500000n} />
119
+ <Receipt.Item label="Item 2" value={2000000n} />
120
+ <Receipt.Separator />
121
+ <Receipt.Subtotal />
122
+ <Receipt.Fee label="Shipping" value={200000n} />
123
+ <Receipt.Total />
124
+ </Receipt>
125
+ </div>
126
+ ),
127
+ };
128
+
129
+ export const FullReceipt: StoryObj<typeof Receipt> = {
130
+ render: () => (
131
+ <div className="bg-surface w-80 rounded-lg border border-border p-4">
132
+ <Receipt decimals={6}>
133
+ <Receipt.Price maxDecimals={2}>
134
+ <Price.Symbol>$</Price.Symbol>
135
+ <Price.Value />
136
+ </Receipt.Price>
137
+ <Receipt.Header className="flex items-baseline justify-between">
138
+ <span className="text-xl font-semibold">Order #12345</span>
139
+ <span className="text-xs leading-[18px] text-muted-foreground">
140
+ March 16, 2026
141
+ </span>
142
+ </Receipt.Header>
143
+ <Receipt.Item label="Product A" value={2500000n} />
144
+ <Receipt.Item label="Product B" value={1800000n} />
145
+ <Receipt.Item label="Product C" value={700000n} />
146
+ <Receipt.Separator />
147
+ <Receipt.Subtotal />
148
+ <Receipt.Discount label="Member Discount" value={500000n} />
149
+ <Receipt.Fee label="Shipping" value={200000n} />
150
+ <Receipt.Tax rate={0.08} />
151
+ <Receipt.Separator />
152
+ <Receipt.Total />
153
+ <Receipt.Footer>
154
+ <span className="text-center text-xs text-muted-foreground">
155
+ Thank you for your order!
156
+ </span>
157
+ </Receipt.Footer>
158
+ </Receipt>
159
+ </div>
160
+ ),
161
+ };
162
+
163
+ export const ManualTotals: StoryObj<typeof Receipt> = {
164
+ render: () => (
165
+ <div className="bg-surface w-80 rounded-lg border border-border p-4">
166
+ <Receipt decimals={2}>
167
+ <Receipt.Price maxDecimals={2}>
168
+ <Price.Symbol>$</Price.Symbol>
169
+ <Price.Value />
170
+ </Receipt.Price>
171
+ <Receipt.Header>
172
+ <span className="text-xl font-semibold">Invoice</span>
173
+ </Receipt.Header>
174
+ <Receipt.Item label="Consulting" value={500000} />
175
+ <Receipt.Item label="Development" value={750000} />
176
+ <Receipt.Separator />
177
+ <Receipt.Subtotal value={1250000} />
178
+ <Receipt.Total value={1500000} label="Amount Due" />
179
+ </Receipt>
180
+ </div>
181
+ ),
182
+ };
183
+
184
+ export const EthReceipt: StoryObj<typeof Receipt> = {
185
+ render: () => (
186
+ <div className="bg-surface w-80 rounded-lg border border-border p-4">
187
+ <Receipt decimals={18}>
188
+ <Receipt.Price maxDecimals={4}>
189
+ <Price.Value /> <Price.Symbol>ETH</Price.Symbol>
190
+ </Receipt.Price>
191
+ <Receipt.Header>
192
+ <span className="text-xl font-semibold">NFT Purchase</span>
193
+ </Receipt.Header>
194
+ <Receipt.Item label="Base Price" value={500000000000000000n} />
195
+ <Receipt.Item label="Royalty" value={25000000000000000n} />
196
+ <Receipt.Separator />
197
+ <Receipt.Total />
198
+ </Receipt>
199
+ </div>
200
+ ),
201
+ };
202
+
203
+ export const PerItemOverride: StoryObj<typeof Receipt> = {
204
+ render: () => (
205
+ <div className="bg-surface w-80 rounded-lg border border-border p-4">
206
+ <Receipt decimals={6}>
207
+ <Receipt.Price maxDecimals={2}>
208
+ <Price.Symbol>$</Price.Symbol>
209
+ <Price.Value />
210
+ </Receipt.Price>
211
+ <Receipt.Header>
212
+ <span className="text-xl font-semibold">Mixed Override</span>
213
+ </Receipt.Header>
214
+ <Receipt.Item label="Normal item" value={1500000n} />
215
+ <Receipt.Item label="High precision" value={1234567n} maxDecimals={6} />
216
+ <Receipt.Separator />
217
+ <Receipt.Total />
218
+ </Receipt>
219
+ </div>
220
+ ),
221
+ };