@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,164 @@
1
+ import { Separator } from "./Separator.js";
2
+ import * as React from "react";
3
+
4
+ //#region src/components/primitives/Receipt.d.ts
5
+ type ReceiptInternalIndexProp = {
6
+ __receiptIndex?: number;
7
+ };
8
+ interface ReceiptProps extends React.ComponentProps<"div"> {
9
+ decimals?: number;
10
+ }
11
+ interface ReceiptPriceProps {
12
+ maxDecimals?: number;
13
+ abbreviate?: boolean;
14
+ children: React.ReactNode;
15
+ }
16
+ declare function ReceiptPrice(_props: ReceiptPriceProps): React.ReactElement;
17
+ interface ReceiptHeaderProps extends React.ComponentProps<"div"> {}
18
+ declare function ReceiptHeader({
19
+ children,
20
+ className,
21
+ ...props
22
+ }: ReceiptHeaderProps): React.ReactElement;
23
+ interface ReceiptItemProps extends Omit<React.ComponentProps<"div">, "children">, ReceiptInternalIndexProp {
24
+ label: string;
25
+ value: bigint | number | string;
26
+ decimals?: number;
27
+ maxDecimals?: number;
28
+ abbreviate?: boolean;
29
+ children?: React.ReactNode;
30
+ }
31
+ declare function ReceiptItem({
32
+ label,
33
+ value,
34
+ decimals,
35
+ maxDecimals,
36
+ abbreviate,
37
+ children,
38
+ className,
39
+ __receiptIndex: _receiptIndex,
40
+ ...props
41
+ }: ReceiptItemProps): React.ReactElement;
42
+ interface ReceiptSeparatorProps extends React.ComponentProps<typeof Separator> {}
43
+ declare function ReceiptSeparator({
44
+ className,
45
+ ...props
46
+ }: ReceiptSeparatorProps): React.ReactElement;
47
+ interface ReceiptSubtotalProps extends React.ComponentProps<"div">, ReceiptInternalIndexProp {
48
+ decimals?: number;
49
+ maxDecimals?: number;
50
+ abbreviate?: boolean;
51
+ label?: string;
52
+ value?: bigint | number | string;
53
+ children?: React.ReactNode;
54
+ }
55
+ declare function ReceiptSubtotal({
56
+ label,
57
+ value,
58
+ decimals,
59
+ maxDecimals,
60
+ abbreviate,
61
+ children,
62
+ className,
63
+ __receiptIndex: _receiptIndex,
64
+ ...props
65
+ }: ReceiptSubtotalProps): React.ReactElement;
66
+ interface ReceiptDiscountProps extends Omit<React.ComponentProps<"div">, "children">, ReceiptInternalIndexProp {
67
+ label: string;
68
+ value: bigint | number | string;
69
+ decimals?: number;
70
+ maxDecimals?: number;
71
+ abbreviate?: boolean;
72
+ children?: React.ReactNode;
73
+ }
74
+ declare function ReceiptDiscount({
75
+ label,
76
+ value,
77
+ decimals,
78
+ maxDecimals,
79
+ abbreviate,
80
+ children,
81
+ className,
82
+ __receiptIndex: _receiptIndex,
83
+ ...props
84
+ }: ReceiptDiscountProps): React.ReactElement;
85
+ interface ReceiptFeeProps extends Omit<React.ComponentProps<"div">, "children">, ReceiptInternalIndexProp {
86
+ label: string;
87
+ value: bigint | number | string;
88
+ decimals?: number;
89
+ maxDecimals?: number;
90
+ abbreviate?: boolean;
91
+ children?: React.ReactNode;
92
+ }
93
+ declare function ReceiptFee({
94
+ label,
95
+ value,
96
+ decimals,
97
+ maxDecimals,
98
+ abbreviate,
99
+ children,
100
+ className,
101
+ __receiptIndex: _receiptIndex,
102
+ ...props
103
+ }: ReceiptFeeProps): React.ReactElement;
104
+ interface ReceiptTaxProps extends Omit<React.ComponentProps<"div">, "children">, ReceiptInternalIndexProp {
105
+ label?: string;
106
+ value?: bigint | number | string;
107
+ rate?: number;
108
+ decimals?: number;
109
+ maxDecimals?: number;
110
+ abbreviate?: boolean;
111
+ children?: React.ReactNode;
112
+ }
113
+ declare function ReceiptTax({
114
+ label,
115
+ value,
116
+ rate,
117
+ decimals,
118
+ maxDecimals,
119
+ abbreviate,
120
+ children,
121
+ className,
122
+ __receiptIndex: _receiptIndex,
123
+ ...props
124
+ }: ReceiptTaxProps): React.ReactElement;
125
+ interface ReceiptTotalProps extends React.ComponentProps<"div">, ReceiptInternalIndexProp {
126
+ label?: string;
127
+ value?: bigint | number | string;
128
+ decimals?: number;
129
+ maxDecimals?: number;
130
+ abbreviate?: boolean;
131
+ children?: React.ReactNode;
132
+ }
133
+ declare function ReceiptTotal({
134
+ label,
135
+ value,
136
+ decimals,
137
+ maxDecimals,
138
+ abbreviate,
139
+ children,
140
+ className,
141
+ __receiptIndex: _receiptIndex,
142
+ ...props
143
+ }: ReceiptTotalProps): React.ReactElement;
144
+ interface ReceiptFooterProps extends React.ComponentProps<"div"> {}
145
+ declare function ReceiptFooter({
146
+ children,
147
+ className,
148
+ ...props
149
+ }: ReceiptFooterProps): React.ReactElement;
150
+ declare const Receipt: {
151
+ (props: ReceiptProps): React.ReactElement;
152
+ Price: typeof ReceiptPrice;
153
+ Header: typeof ReceiptHeader;
154
+ Item: typeof ReceiptItem;
155
+ Separator: typeof ReceiptSeparator;
156
+ Subtotal: typeof ReceiptSubtotal;
157
+ Discount: typeof ReceiptDiscount;
158
+ Fee: typeof ReceiptFee;
159
+ Tax: typeof ReceiptTax;
160
+ Total: typeof ReceiptTotal;
161
+ Footer: typeof ReceiptFooter;
162
+ };
163
+ //#endregion
164
+ export { Receipt, ReceiptDiscountProps, ReceiptFeeProps, ReceiptFooterProps, ReceiptHeaderProps, ReceiptItemProps, ReceiptPriceProps, ReceiptProps, ReceiptSeparatorProps, ReceiptSubtotalProps, ReceiptTaxProps, ReceiptTotalProps };
@@ -0,0 +1,344 @@
1
+ "use client";
2
+
3
+ import { cn } from "../../lib/cn.js";
4
+ import { Price } from "./Price.js";
5
+ import { Separator } from "./Separator.js";
6
+ import * as React from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+
9
+ //#region src/components/primitives/Receipt.tsx
10
+ function toBigInt(value) {
11
+ if (typeof value === "bigint") return value;
12
+ try {
13
+ return BigInt(value);
14
+ } catch {
15
+ return BigInt(0);
16
+ }
17
+ }
18
+ function scaleValue(value, fromDecimals, toDecimals) {
19
+ const normalizedValue = toBigInt(value);
20
+ if (fromDecimals === toDecimals) return normalizedValue;
21
+ const scale = BigInt(10 ** Math.abs(toDecimals - fromDecimals));
22
+ return fromDecimals < toDecimals ? normalizedValue * scale : normalizedValue / scale;
23
+ }
24
+ function computeTaxFromRate(subtotal, decimals, rate) {
25
+ const taxNum = Number(subtotal) / 10 ** decimals * rate;
26
+ const multiplier = BigInt(10 ** decimals);
27
+ return BigInt(Math.round(taxNum * Number(multiplier)));
28
+ }
29
+ const ReceiptContext = React.createContext(null);
30
+ function useReceiptContext() {
31
+ const context = React.useContext(ReceiptContext);
32
+ if (!context) throw new Error("Receipt components must be used within a Receipt root");
33
+ return context;
34
+ }
35
+ const ReceiptPriceContext = React.createContext(null);
36
+ function useReceiptPriceDefaults() {
37
+ return React.useContext(ReceiptPriceContext);
38
+ }
39
+ function isElementOfType(child, component) {
40
+ return React.isValidElement(child) && child.type === component;
41
+ }
42
+ function getDisplayValue(explicitValue, fallbackValue) {
43
+ return explicitValue !== void 0 ? toBigInt(explicitValue) : fallbackValue;
44
+ }
45
+ function computeReceiptValues(descriptors, receiptDecimals) {
46
+ const subtotals = /* @__PURE__ */ new Map();
47
+ const taxes = /* @__PURE__ */ new Map();
48
+ const totals = /* @__PURE__ */ new Map();
49
+ let subtotalAccumulator = BigInt(0);
50
+ let positiveAccumulator = BigInt(0);
51
+ let negativeAccumulator = BigInt(0);
52
+ for (const descriptor of descriptors) switch (descriptor.kind) {
53
+ case "item": {
54
+ const scaledValue = scaleValue(descriptor.value ?? 0, descriptor.decimals, receiptDecimals);
55
+ subtotalAccumulator += scaledValue;
56
+ positiveAccumulator += scaledValue;
57
+ break;
58
+ }
59
+ case "discount": {
60
+ const scaledValue = scaleValue(descriptor.value ?? 0, descriptor.decimals, receiptDecimals);
61
+ negativeAccumulator += scaledValue;
62
+ break;
63
+ }
64
+ case "fee": {
65
+ const scaledValue = scaleValue(descriptor.value ?? 0, descriptor.decimals, receiptDecimals);
66
+ positiveAccumulator += scaledValue;
67
+ break;
68
+ }
69
+ case "subtotal":
70
+ subtotals.set(descriptor.index, subtotalAccumulator);
71
+ break;
72
+ case "tax": {
73
+ const explicitValue = descriptor.value;
74
+ const computedTax = explicitValue !== void 0 ? scaleValue(explicitValue, descriptor.decimals, receiptDecimals) : descriptor.rate !== void 0 ? computeTaxFromRate(scaleValue(subtotalAccumulator, receiptDecimals, descriptor.decimals), descriptor.decimals, descriptor.rate) : BigInt(0);
75
+ taxes.set(descriptor.index, scaleValue(computedTax, descriptor.decimals, receiptDecimals));
76
+ positiveAccumulator += scaleValue(computedTax, descriptor.decimals, receiptDecimals);
77
+ break;
78
+ }
79
+ case "total":
80
+ totals.set(descriptor.index, positiveAccumulator - negativeAccumulator);
81
+ break;
82
+ }
83
+ return {
84
+ subtotals,
85
+ taxes,
86
+ totals
87
+ };
88
+ }
89
+ function ReceiptPrice(_props) {
90
+ return null;
91
+ }
92
+ function ReceiptHeader({ children, className, ...props }) {
93
+ return /* @__PURE__ */ jsx("div", {
94
+ className: cn("text-foreground pb-2", className),
95
+ ...props,
96
+ children
97
+ });
98
+ }
99
+ function ReceiptItem({ label, value, decimals, maxDecimals, abbreviate, children, className, __receiptIndex: _receiptIndex, ...props }) {
100
+ const context = useReceiptContext();
101
+ const defaults = useReceiptPriceDefaults();
102
+ const itemDecimals = decimals ?? context.decimals;
103
+ const priceChildren = children ?? defaults?.template;
104
+ const priceMaxDecimals = maxDecimals ?? defaults?.maxDecimals;
105
+ const priceAbbreviate = abbreviate ?? defaults?.abbreviate;
106
+ return /* @__PURE__ */ jsxs("div", {
107
+ className: cn("flex items-center justify-between gap-4", className),
108
+ ...props,
109
+ children: [/* @__PURE__ */ jsx("span", {
110
+ className: "text-muted-foreground",
111
+ children: label
112
+ }), /* @__PURE__ */ jsx(Price, {
113
+ value,
114
+ decimals: itemDecimals,
115
+ maxDecimals: priceMaxDecimals,
116
+ abbreviate: priceAbbreviate,
117
+ className: "text-foreground",
118
+ children: priceChildren
119
+ })]
120
+ });
121
+ }
122
+ function ReceiptSeparator({ className, ...props }) {
123
+ return /* @__PURE__ */ jsx(Separator, {
124
+ className: cn("my-1", className),
125
+ ...props
126
+ });
127
+ }
128
+ function ReceiptSubtotal({ label = "Subtotal", value, decimals, maxDecimals, abbreviate, children, className, __receiptIndex: _receiptIndex, ...props }) {
129
+ const context = useReceiptContext();
130
+ const defaults = useReceiptPriceDefaults();
131
+ const displayDecimals = decimals ?? context.decimals;
132
+ const priceChildren = children ?? defaults?.template;
133
+ const priceMaxDecimals = maxDecimals ?? defaults?.maxDecimals;
134
+ const priceAbbreviate = abbreviate ?? defaults?.abbreviate;
135
+ const displayValue = getDisplayValue(value, scaleValue(_receiptIndex !== void 0 ? context.computed.subtotals.get(_receiptIndex) ?? BigInt(0) : BigInt(0), context.decimals, displayDecimals));
136
+ return /* @__PURE__ */ jsxs("div", {
137
+ className: cn("flex items-center justify-between gap-4", className),
138
+ ...props,
139
+ children: [/* @__PURE__ */ jsx("span", {
140
+ className: "text-muted-foreground",
141
+ children: label
142
+ }), /* @__PURE__ */ jsx(Price, {
143
+ value: displayValue,
144
+ decimals: displayDecimals,
145
+ maxDecimals: priceMaxDecimals,
146
+ abbreviate: priceAbbreviate,
147
+ className: "text-foreground",
148
+ children: priceChildren
149
+ })]
150
+ });
151
+ }
152
+ function ReceiptDiscount({ label, value, decimals, maxDecimals, abbreviate, children, className, __receiptIndex: _receiptIndex, ...props }) {
153
+ const context = useReceiptContext();
154
+ const defaults = useReceiptPriceDefaults();
155
+ const displayDecimals = decimals ?? context.decimals;
156
+ const priceChildren = children ?? defaults?.template;
157
+ const priceMaxDecimals = maxDecimals ?? defaults?.maxDecimals;
158
+ const priceAbbreviate = abbreviate ?? defaults?.abbreviate;
159
+ return /* @__PURE__ */ jsxs("div", {
160
+ className: cn("flex items-center justify-between gap-4", className),
161
+ ...props,
162
+ children: [/* @__PURE__ */ jsx("span", {
163
+ className: "text-muted-foreground",
164
+ children: label
165
+ }), /* @__PURE__ */ jsxs("span", {
166
+ className: "text-foreground",
167
+ children: ["-", /* @__PURE__ */ jsx(Price, {
168
+ value,
169
+ decimals: displayDecimals,
170
+ maxDecimals: priceMaxDecimals,
171
+ abbreviate: priceAbbreviate,
172
+ className: "text-foreground",
173
+ children: priceChildren
174
+ })]
175
+ })]
176
+ });
177
+ }
178
+ function ReceiptFee({ label, value, decimals, maxDecimals, abbreviate, children, className, __receiptIndex: _receiptIndex, ...props }) {
179
+ const context = useReceiptContext();
180
+ const defaults = useReceiptPriceDefaults();
181
+ const displayDecimals = decimals ?? context.decimals;
182
+ const priceChildren = children ?? defaults?.template;
183
+ const priceMaxDecimals = maxDecimals ?? defaults?.maxDecimals;
184
+ const priceAbbreviate = abbreviate ?? defaults?.abbreviate;
185
+ return /* @__PURE__ */ jsxs("div", {
186
+ className: cn("flex items-center justify-between gap-4", className),
187
+ ...props,
188
+ children: [/* @__PURE__ */ jsx("span", {
189
+ className: "text-muted-foreground",
190
+ children: label
191
+ }), /* @__PURE__ */ jsx(Price, {
192
+ value,
193
+ decimals: displayDecimals,
194
+ maxDecimals: priceMaxDecimals,
195
+ abbreviate: priceAbbreviate,
196
+ className: "text-foreground",
197
+ children: priceChildren
198
+ })]
199
+ });
200
+ }
201
+ function ReceiptTax({ label = "Tax", value, rate, decimals, maxDecimals, abbreviate, children, className, __receiptIndex: _receiptIndex, ...props }) {
202
+ const context = useReceiptContext();
203
+ const defaults = useReceiptPriceDefaults();
204
+ const displayDecimals = decimals ?? context.decimals;
205
+ const priceChildren = children ?? defaults?.template;
206
+ const priceMaxDecimals = maxDecimals ?? defaults?.maxDecimals;
207
+ const priceAbbreviate = abbreviate ?? defaults?.abbreviate;
208
+ const displayValue = getDisplayValue(value, scaleValue(_receiptIndex !== void 0 ? context.computed.taxes.get(_receiptIndex) ?? BigInt(0) : BigInt(0), context.decimals, displayDecimals));
209
+ return /* @__PURE__ */ jsxs("div", {
210
+ className: cn("flex items-center justify-between gap-4", className),
211
+ ...props,
212
+ children: [/* @__PURE__ */ jsxs("span", {
213
+ className: "text-muted-foreground",
214
+ children: [label, rate !== void 0 && /* @__PURE__ */ jsxs("span", { children: [
215
+ " (",
216
+ parseFloat((rate * 100).toPrecision(10)),
217
+ "%)"
218
+ ] })]
219
+ }), /* @__PURE__ */ jsx(Price, {
220
+ value: displayValue,
221
+ decimals: displayDecimals,
222
+ maxDecimals: priceMaxDecimals,
223
+ abbreviate: priceAbbreviate,
224
+ className: "text-foreground",
225
+ children: priceChildren
226
+ })]
227
+ });
228
+ }
229
+ function ReceiptTotal({ label = "Total", value, decimals, maxDecimals, abbreviate, children, className, __receiptIndex: _receiptIndex, ...props }) {
230
+ const context = useReceiptContext();
231
+ const defaults = useReceiptPriceDefaults();
232
+ const displayDecimals = decimals ?? context.decimals;
233
+ const priceChildren = children ?? defaults?.template;
234
+ const priceMaxDecimals = maxDecimals ?? defaults?.maxDecimals;
235
+ const priceAbbreviate = abbreviate ?? defaults?.abbreviate;
236
+ const displayValue = getDisplayValue(value, scaleValue(_receiptIndex !== void 0 ? context.computed.totals.get(_receiptIndex) ?? BigInt(0) : BigInt(0), context.decimals, displayDecimals));
237
+ return /* @__PURE__ */ jsxs("div", {
238
+ className: cn("text-foreground flex items-center justify-between gap-4 pt-2 font-medium", className),
239
+ ...props,
240
+ children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx("span", {
241
+ className: "text-foreground",
242
+ children: /* @__PURE__ */ jsx(Price, {
243
+ value: displayValue,
244
+ decimals: displayDecimals,
245
+ maxDecimals: priceMaxDecimals,
246
+ abbreviate: priceAbbreviate,
247
+ className: "text-foreground",
248
+ children: priceChildren
249
+ })
250
+ })]
251
+ });
252
+ }
253
+ function ReceiptFooter({ children, className, ...props }) {
254
+ return /* @__PURE__ */ jsx("div", {
255
+ className: cn("pt-2 text-xs leading-[18px] text-muted-foreground", className),
256
+ ...props,
257
+ children
258
+ });
259
+ }
260
+ function ReceiptRoot({ children, className, decimals = 6, ...props }) {
261
+ let priceDefaults = null;
262
+ const calculationDescriptors = [];
263
+ const renderedChildren = React.Children.toArray(children).flatMap((child, index) => {
264
+ if (isElementOfType(child, ReceiptPrice)) {
265
+ const { children: template, maxDecimals, abbreviate = false } = child.props;
266
+ priceDefaults = {
267
+ template,
268
+ maxDecimals,
269
+ abbreviate
270
+ };
271
+ return [];
272
+ }
273
+ if (!React.isValidElement(child)) return [child];
274
+ if (isElementOfType(child, ReceiptItem)) calculationDescriptors.push({
275
+ index,
276
+ kind: "item",
277
+ value: child.props.value,
278
+ decimals: child.props.decimals ?? decimals
279
+ });
280
+ else if (isElementOfType(child, ReceiptDiscount)) calculationDescriptors.push({
281
+ index,
282
+ kind: "discount",
283
+ value: child.props.value,
284
+ decimals: child.props.decimals ?? decimals
285
+ });
286
+ else if (isElementOfType(child, ReceiptFee)) calculationDescriptors.push({
287
+ index,
288
+ kind: "fee",
289
+ value: child.props.value,
290
+ decimals: child.props.decimals ?? decimals
291
+ });
292
+ else if (isElementOfType(child, ReceiptSubtotal)) calculationDescriptors.push({
293
+ index,
294
+ kind: "subtotal",
295
+ value: child.props.value,
296
+ decimals: child.props.decimals ?? decimals
297
+ });
298
+ else if (isElementOfType(child, ReceiptTax)) calculationDescriptors.push({
299
+ index,
300
+ kind: "tax",
301
+ value: child.props.value,
302
+ rate: child.props.rate,
303
+ decimals: child.props.decimals ?? decimals
304
+ });
305
+ else if (isElementOfType(child, ReceiptTotal)) calculationDescriptors.push({
306
+ index,
307
+ kind: "total",
308
+ value: child.props.value,
309
+ decimals: child.props.decimals ?? decimals
310
+ });
311
+ else return [child];
312
+ return [React.cloneElement(child, { __receiptIndex: index })];
313
+ });
314
+ const computed = React.useMemo(() => computeReceiptValues(calculationDescriptors, decimals), [decimals]);
315
+ return /* @__PURE__ */ jsx(ReceiptContext, {
316
+ value: React.useMemo(() => ({
317
+ decimals,
318
+ computed
319
+ }), [decimals, computed]),
320
+ children: /* @__PURE__ */ jsx(ReceiptPriceContext, {
321
+ value: priceDefaults,
322
+ children: /* @__PURE__ */ jsx("div", {
323
+ className: cn("flex flex-col gap-2 text-sm leading-[21px] text-foreground", className),
324
+ ...props,
325
+ children: renderedChildren
326
+ })
327
+ })
328
+ });
329
+ }
330
+ const Receipt = Object.assign(ReceiptRoot, {
331
+ Price: ReceiptPrice,
332
+ Header: ReceiptHeader,
333
+ Item: ReceiptItem,
334
+ Separator: ReceiptSeparator,
335
+ Subtotal: ReceiptSubtotal,
336
+ Discount: ReceiptDiscount,
337
+ Fee: ReceiptFee,
338
+ Tax: ReceiptTax,
339
+ Total: ReceiptTotal,
340
+ Footer: ReceiptFooter
341
+ });
342
+
343
+ //#endregion
344
+ export { Receipt };
@@ -0,0 +1,67 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/components/primitives/Scale.d.ts
4
+ type ScaleValue = number | bigint;
5
+ type SnapMode = "up" | "down" | "nearest";
6
+ interface ScaleContextValue<T extends ScaleValue> {
7
+ domain: [T, T];
8
+ getTickSize: (value: T) => T;
9
+ snapMode: SnapMode | false;
10
+ getValueAtPosition: (position: number) => T;
11
+ }
12
+ interface TickContext<T extends ScaleValue> {
13
+ /** The position on the scale (0-1) */
14
+ position: number;
15
+ /** The calculated value at this position (snapped to tick grid) */
16
+ value: T;
17
+ }
18
+ declare function useScale<T extends ScaleValue>(): ScaleContextValue<T>;
19
+ interface LinearProps<T extends ScaleValue> {
20
+ /** Domain tuple: [min, max] */
21
+ domain: [T, T];
22
+ /** Function to get tick size at a given value */
23
+ getTickSize: (value: T) => T;
24
+ /** How to snap values to the tick grid (default: 'nearest', false to disable) */
25
+ snapMode?: SnapMode | false;
26
+ children: React.ReactNode;
27
+ className?: string;
28
+ }
29
+ declare function Linear<T extends ScaleValue>({
30
+ domain,
31
+ getTickSize,
32
+ snapMode,
33
+ children,
34
+ className
35
+ }: LinearProps<T>): React.ReactElement;
36
+ interface TickProps<T extends ScaleValue> {
37
+ /** Position on the scale (0 = min, 1 = max) */
38
+ position: number;
39
+ /** Render function receiving the tick context */
40
+ children: (context: TickContext<T>) => React.ReactNode;
41
+ className?: string;
42
+ }
43
+ declare function Tick<T extends ScaleValue>({
44
+ position,
45
+ children,
46
+ className
47
+ }: TickProps<T>): React.ReactElement;
48
+ interface TicksProps<T extends ScaleValue> {
49
+ /** Number of ticks to generate (evenly spaced from 0 to 1) */
50
+ count: number;
51
+ /** Render function for each tick */
52
+ children: (context: TickContext<T>, index: number) => React.ReactNode;
53
+ className?: string;
54
+ }
55
+ declare function Ticks<T extends ScaleValue>({
56
+ count,
57
+ children,
58
+ className
59
+ }: TicksProps<T>): React.ReactElement;
60
+ interface ScaleComponent {
61
+ Linear: typeof Linear;
62
+ Tick: typeof Tick;
63
+ Ticks: typeof Ticks;
64
+ }
65
+ declare const Scale: ScaleComponent;
66
+ //#endregion
67
+ export { Scale, type ScaleValue, type SnapMode, TickContext, useScale };
@@ -0,0 +1,132 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { Fragment, jsx } from "react/jsx-runtime";
5
+
6
+ //#region src/components/primitives/Scale.tsx
7
+ const ScaleContext = React.createContext(null);
8
+ function useScale() {
9
+ const context = React.useContext(ScaleContext);
10
+ if (!context) throw new Error("useScale must be used within Scale.Linear");
11
+ return context;
12
+ }
13
+ /**
14
+ * Type guard to check if a value is bigint
15
+ */
16
+ function isBigInt(value) {
17
+ return typeof value === "bigint";
18
+ }
19
+ /**
20
+ * Linearly interpolate between min and max based on position (0-1).
21
+ * Works with both number and bigint.
22
+ */
23
+ function interpolate(min, max, position) {
24
+ const clampedPosition = Math.max(0, Math.min(1, position));
25
+ if (isBigInt(min) && isBigInt(max)) return min + (max - min) * BigInt(Math.round(clampedPosition * 1e6)) / 1000000n;
26
+ const numMin = min;
27
+ return numMin + (max - numMin) * clampedPosition;
28
+ }
29
+ /**
30
+ * Snaps a value to the tick grid based on the specified mode.
31
+ * Works with both number and bigint.
32
+ */
33
+ function snapToTick(value, tickSize, mode, min) {
34
+ if (isBigInt(value) && isBigInt(tickSize)) {
35
+ if (tickSize <= 0n) return value;
36
+ const remainder = value % tickSize;
37
+ if (remainder === 0n) return value;
38
+ let snapped;
39
+ switch (mode) {
40
+ case "up":
41
+ snapped = value - remainder + tickSize;
42
+ break;
43
+ case "down":
44
+ snapped = value - remainder;
45
+ break;
46
+ case "nearest":
47
+ snapped = remainder * 2n >= tickSize ? value - remainder + tickSize : value - remainder;
48
+ break;
49
+ }
50
+ if (min !== void 0 && isBigInt(min) && snapped < min) snapped = min;
51
+ return snapped;
52
+ }
53
+ const numValue = value;
54
+ const numTickSize = tickSize;
55
+ const numMin = min;
56
+ if (numTickSize <= 0) return value;
57
+ const remainder = numValue % numTickSize;
58
+ if (Math.abs(remainder) < Number.EPSILON) return value;
59
+ let snapped;
60
+ switch (mode) {
61
+ case "up":
62
+ snapped = numValue - remainder + numTickSize;
63
+ break;
64
+ case "down":
65
+ snapped = numValue - remainder;
66
+ break;
67
+ case "nearest":
68
+ snapped = remainder * 2 >= numTickSize ? numValue - remainder + numTickSize : numValue - remainder;
69
+ break;
70
+ }
71
+ if (numMin !== void 0 && snapped < numMin) snapped = numMin;
72
+ return snapped;
73
+ }
74
+ function Linear({ domain, getTickSize, snapMode = "nearest", children, className }) {
75
+ const [min, max] = domain;
76
+ const getValueAtPosition = React.useCallback((position) => {
77
+ const rawValue = interpolate(min, max, position);
78
+ if (snapMode === false) return rawValue;
79
+ return snapToTick(rawValue, getTickSize(rawValue), snapMode, min);
80
+ }, [
81
+ min,
82
+ max,
83
+ getTickSize,
84
+ snapMode
85
+ ]);
86
+ const contextValue = React.useMemo(() => ({
87
+ domain,
88
+ getTickSize,
89
+ snapMode,
90
+ getValueAtPosition
91
+ }), [
92
+ domain,
93
+ getTickSize,
94
+ snapMode,
95
+ getValueAtPosition
96
+ ]);
97
+ return /* @__PURE__ */ jsx(ScaleContext.Provider, {
98
+ value: contextValue,
99
+ children: /* @__PURE__ */ jsx("div", {
100
+ className,
101
+ children
102
+ })
103
+ });
104
+ }
105
+ function Tick({ position, children, className }) {
106
+ const { getValueAtPosition } = useScale();
107
+ return /* @__PURE__ */ jsx("div", {
108
+ className,
109
+ children: children({
110
+ position,
111
+ value: React.useMemo(() => getValueAtPosition(position), [getValueAtPosition, position])
112
+ })
113
+ });
114
+ }
115
+ function Ticks({ count, children, className }) {
116
+ return /* @__PURE__ */ jsx(Fragment, { children: React.useMemo(() => {
117
+ if (count <= 1) return [0];
118
+ return Array.from({ length: count }, (_, i) => i / (count - 1));
119
+ }, [count]).map((position, index) => /* @__PURE__ */ jsx(Tick, {
120
+ position,
121
+ className,
122
+ children: (context) => children(context, index)
123
+ }, position)) });
124
+ }
125
+ const Scale = {
126
+ Linear,
127
+ Tick,
128
+ Ticks
129
+ };
130
+
131
+ //#endregion
132
+ export { Scale, useScale };