@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,22 @@
1
+ "use client";
2
+
3
+ import { useCountdown } from "../../../hooks/useCountdown.js";
4
+ import { Text } from "../Text.js";
5
+ import { Fragment, jsx } from "react/jsx-runtime";
6
+
7
+ //#region src/components/primitives/countdown/Countdown.tsx
8
+ function Countdown({ to, showWhenExpired = false, stopOnExpired = false, className, children }) {
9
+ const result = useCountdown(to, { stopOnExpired });
10
+ if (!showWhenExpired && result.remainingMs === null) return null;
11
+ const display = result.timeString ?? "00d:00h:00m:00s";
12
+ if (children) return /* @__PURE__ */ jsx(Fragment, { children: children(result) });
13
+ return /* @__PURE__ */ jsx(Text, {
14
+ className,
15
+ tabularNums: true,
16
+ suppressHydrationWarning: true,
17
+ children: display
18
+ });
19
+ }
20
+
21
+ //#endregion
22
+ export { Countdown };
@@ -0,0 +1,13 @@
1
+ //#region src/components/primitives/framed-image/FramedImage.d.ts
2
+ interface FramedImageProps {
3
+ src: string;
4
+ alt?: string;
5
+ className?: string;
6
+ }
7
+ declare function FramedImage({
8
+ src,
9
+ alt,
10
+ className
11
+ }: FramedImageProps): React.ReactElement;
12
+ //#endregion
13
+ export { FramedImage, FramedImageProps };
@@ -0,0 +1,37 @@
1
+ "use client";
2
+
3
+ import { cn } from "../../../lib/cn.js";
4
+ import { MorphDialog } from "../MorphDialog.js";
5
+ import { jsx } from "react/jsx-runtime";
6
+ import { motion } from "motion/react";
7
+
8
+ //#region src/components/primitives/framed-image/FramedImage.tsx
9
+ function FramedImage({ src, alt, className }) {
10
+ return /* @__PURE__ */ jsx(MorphDialog, {
11
+ className: cn("relative h-full min-h-0 w-full min-w-0 flex-1 rounded-md bg-accent", className),
12
+ triggerClassName: "h-full w-full",
13
+ popupClassName: "flex items-center justify-center",
14
+ popupAriaLabel: alt ?? "Expanded image preview",
15
+ contentClosesDialog: true,
16
+ trigger: /* @__PURE__ */ jsx("div", {
17
+ className: "absolute inset-0 flex items-center justify-center p-5",
18
+ children: /* @__PURE__ */ jsx(motion.img, {
19
+ src,
20
+ alt: alt ?? "",
21
+ className: "h-full w-full cursor-pointer object-contain",
22
+ whileHover: { scale: 1.02 }
23
+ })
24
+ }),
25
+ content: /* @__PURE__ */ jsx("div", {
26
+ className: "flex items-center justify-center",
27
+ children: /* @__PURE__ */ jsx("img", {
28
+ src,
29
+ alt: alt ?? "",
30
+ className: "block max-h-[90vh] max-w-[90vw] rounded-lg object-contain"
31
+ })
32
+ })
33
+ });
34
+ }
35
+
36
+ //#endregion
37
+ export { FramedImage };
@@ -0,0 +1,17 @@
1
+ import { FramedImage, FramedImageProps } from "./framed-image/FramedImage.js";
2
+ import { Button, ButtonElement, ButtonProps, buttonVariants } from "./Button.js";
3
+ import { Countdown, CountdownProps } from "./countdown/Countdown.js";
4
+ import { Drawer, DrawerProps } from "./Drawer.js";
5
+ import { Feedback } from "./Feedback.js";
6
+ import { MorphDialog, MorphDialogProps } from "./MorphDialog.js";
7
+ import { FormatPriceOptions, Price, PriceProps, PriceSymbolProps, PriceValueProps, formatPrice } from "./Price.js";
8
+ import { CursorGrowIcon, SteppedInput } from "./SteppedInput.js";
9
+ import { PriceInput } from "./PriceInput.js";
10
+ import { Separator } from "./Separator.js";
11
+ import { Receipt, ReceiptDiscountProps, ReceiptFeeProps, ReceiptFooterProps, ReceiptHeaderProps, ReceiptItemProps, ReceiptPriceProps, ReceiptProps, ReceiptSeparatorProps, ReceiptSubtotalProps, ReceiptTaxProps, ReceiptTotalProps } from "./Receipt.js";
12
+ import { GroupItemContextValue, RankedList, RankedListProps, Ranking, RankingProps, SlotContext, SlotProps } from "./ranked-list/Ranking.js";
13
+ import { Scale, ScaleValue, SnapMode, TickContext, useScale } from "./Scale.js";
14
+ import { Skeleton, SkeletonElement, SkeletonProps } from "./Skeleton.js";
15
+ import { Tab, Tabs, TabsContextType, TabsIndicator, TabsList, TabsPanel } from "./Tabs.js";
16
+ import { Text, TextElement, TextProps, textVariants } from "./Text.js";
17
+ import { Tag, TagElement, TagProps } from "./Tag.js";
@@ -0,0 +1,117 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/components/primitives/ranked-list/Ranking.d.ts
4
+ interface SlotContext {
5
+ globalIndex: number;
6
+ groupIndex: number;
7
+ rank: number;
8
+ rankInGroup: number;
9
+ isFirstInGroup: boolean;
10
+ isLastInGroup: boolean;
11
+ isLastItem: boolean;
12
+ }
13
+ type SlotChildren = React.ReactNode | ((context: SlotContext) => React.ReactNode);
14
+ interface GroupItemContextValue<T> {
15
+ item: T;
16
+ globalIndex: number;
17
+ groupIndex: number;
18
+ rank: number;
19
+ rankInGroup: number;
20
+ isFirstInGroup: boolean;
21
+ isLastInGroup: boolean;
22
+ isLastItem: boolean;
23
+ }
24
+ interface EmptyProps {
25
+ children: React.ReactNode;
26
+ className?: string;
27
+ }
28
+ declare function Empty({
29
+ children,
30
+ className
31
+ }: EmptyProps): React.ReactElement;
32
+ interface SlotProps {
33
+ slotKey: string;
34
+ atIndex: number;
35
+ children: SlotChildren;
36
+ }
37
+ declare function Slot({
38
+ slotKey: _slotKey,
39
+ atIndex: _atIndex,
40
+ children: _children
41
+ }: SlotProps): React.ReactElement | null;
42
+ interface RankingProps<T> {
43
+ items: T[];
44
+ children: React.ReactNode;
45
+ getKey: (item: T) => string;
46
+ boundaries?: number[];
47
+ labels?: string[];
48
+ className?: string;
49
+ }
50
+ declare function RankingRoot<T>({
51
+ items,
52
+ children,
53
+ getKey,
54
+ boundaries,
55
+ labels,
56
+ className
57
+ }: RankingProps<T>): React.ReactElement;
58
+ interface GroupProps {
59
+ children: React.ReactNode;
60
+ className?: string;
61
+ }
62
+ declare function Group({
63
+ children,
64
+ className
65
+ }: GroupProps): React.ReactElement;
66
+ interface GroupItemProps {
67
+ children: React.ReactNode;
68
+ className?: string;
69
+ }
70
+ declare function GroupItem({
71
+ children,
72
+ className
73
+ }: GroupItemProps): React.ReactElement;
74
+ interface GroupItemIndexProps {
75
+ children?: (context: {
76
+ globalIndex: number;
77
+ rank: number;
78
+ groupIndex: number;
79
+ }) => React.ReactNode;
80
+ className?: string;
81
+ }
82
+ declare function GroupItemIndex({
83
+ children,
84
+ className
85
+ }: GroupItemIndexProps): React.ReactElement | null;
86
+ interface GroupItemValueProps<T> {
87
+ children: (item: T, context: GroupItemContextValue<T>) => React.ReactNode;
88
+ }
89
+ declare function GroupItemValue<T>({
90
+ children
91
+ }: GroupItemValueProps<T>): React.ReactElement | null;
92
+ interface GroupDividerProps {
93
+ children?: (context: {
94
+ label: string;
95
+ groupIndex: number;
96
+ }) => React.ReactNode;
97
+ className?: string;
98
+ }
99
+ declare function GroupDivider({
100
+ children,
101
+ className
102
+ }: GroupDividerProps): React.ReactElement | null;
103
+ interface RankingComponent {
104
+ Root: typeof RankingRoot;
105
+ Empty: typeof Empty;
106
+ Slot: typeof Slot;
107
+ Group: typeof Group;
108
+ GroupItem: typeof GroupItem;
109
+ GroupItemIndex: typeof GroupItemIndex;
110
+ GroupItemValue: typeof GroupItemValue;
111
+ GroupDivider: typeof GroupDivider;
112
+ }
113
+ declare const Ranking: RankingComponent;
114
+ declare const RankedList: RankingComponent;
115
+ type RankedListProps<T> = RankingProps<T>;
116
+ //#endregion
117
+ export { type GroupItemContextValue, RankedList, type RankedListProps, Ranking, type RankingProps, type SlotContext, type SlotProps };
@@ -0,0 +1,219 @@
1
+ "use client";
2
+
3
+ import { cn } from "../../../lib/cn.js";
4
+ import { Text } from "../Text.js";
5
+ import { Separator } from "../Separator.js";
6
+ import * as React from "react";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+
9
+ //#region src/components/primitives/ranked-list/Ranking.tsx
10
+ const RankingContext = React.createContext(null);
11
+ function useRanking() {
12
+ const context = React.useContext(RankingContext);
13
+ if (!context) throw new Error("useRanking must be used within Ranking.Root");
14
+ return context;
15
+ }
16
+ const GroupContext = React.createContext(null);
17
+ function useGroup() {
18
+ const context = React.useContext(GroupContext);
19
+ if (!context) throw new Error("useGroup must be used within Ranking.Group");
20
+ return context;
21
+ }
22
+ const GroupItemContext = React.createContext(null);
23
+ function useGroupItem() {
24
+ const context = React.useContext(GroupItemContext);
25
+ if (!context) throw new Error("useGroupItem must be used within Ranking.GroupItem");
26
+ return context;
27
+ }
28
+ function Empty({ children, className }) {
29
+ return /* @__PURE__ */ jsx("div", {
30
+ className: cn("flex flex-1 items-center justify-center", className),
31
+ children
32
+ });
33
+ }
34
+ function Slot({ slotKey: _slotKey, atIndex: _atIndex, children: _children }) {
35
+ return null;
36
+ }
37
+ function isElementOfType(child, component) {
38
+ return React.isValidElement(child) && child.type === component;
39
+ }
40
+ function RankingRoot({ items, children, getKey, boundaries = [], labels = [], className }) {
41
+ const childArray = React.Children.toArray(children);
42
+ const emptyChild = childArray.find((child) => isElementOfType(child, Empty));
43
+ const slots = childArray.flatMap((child) => {
44
+ if (!isElementOfType(child, Slot)) return [];
45
+ return [{
46
+ key: child.props.slotKey,
47
+ atIndex: child.props.atIndex,
48
+ children: child.props.children
49
+ }];
50
+ });
51
+ const otherChildren = childArray.filter((child) => !isElementOfType(child, Empty) && !isElementOfType(child, Slot));
52
+ const entries = React.useMemo(() => {
53
+ const result = items.map((item) => ({
54
+ type: "item",
55
+ item,
56
+ key: getKey(item)
57
+ }));
58
+ const sortedSlots = [...slots].sort((a, b) => a.atIndex - b.atIndex);
59
+ let offset = 0;
60
+ for (const spec of sortedSlots) {
61
+ const slotEntry = {
62
+ type: "slot",
63
+ spec
64
+ };
65
+ const insertAt = Math.max(0, Math.min(spec.atIndex, items.length)) + offset;
66
+ result.splice(insertAt, 0, slotEntry);
67
+ offset++;
68
+ }
69
+ return result;
70
+ }, [
71
+ items,
72
+ slots,
73
+ getKey
74
+ ]);
75
+ if (entries.length === 0) return /* @__PURE__ */ jsx("div", {
76
+ className,
77
+ children: emptyChild ? emptyChild : /* @__PURE__ */ jsx(Empty, { children: /* @__PURE__ */ jsx(Text, {
78
+ color: "tertiary",
79
+ children: "No items"
80
+ }) })
81
+ });
82
+ return /* @__PURE__ */ jsx("div", {
83
+ className,
84
+ children: /* @__PURE__ */ jsx(RankingContext.Provider, {
85
+ value: {
86
+ items,
87
+ entries,
88
+ boundaries,
89
+ labels,
90
+ getKey
91
+ },
92
+ children: otherChildren
93
+ })
94
+ });
95
+ }
96
+ function Group({ children, className }) {
97
+ const { entries, boundaries, labels } = useRanking();
98
+ const groups = [];
99
+ let currentGroupEntries = [];
100
+ let currentGroupStartIndex = 0;
101
+ let currentGroupIndex = 0;
102
+ let nextBoundary = boundaries[0] ?? Infinity;
103
+ entries.forEach((entry, index) => {
104
+ if (index >= nextBoundary) {
105
+ groups.push({
106
+ label: labels[currentGroupIndex] ?? `Group ${currentGroupIndex + 1}`,
107
+ startIndex: currentGroupStartIndex,
108
+ entries: currentGroupEntries
109
+ });
110
+ currentGroupEntries = [];
111
+ currentGroupStartIndex = index;
112
+ currentGroupIndex++;
113
+ nextBoundary = boundaries[currentGroupIndex] ?? Infinity;
114
+ }
115
+ currentGroupEntries.push(entry);
116
+ });
117
+ if (currentGroupEntries.length > 0) groups.push({
118
+ label: labels[currentGroupIndex] ?? `Group ${currentGroupIndex + 1}`,
119
+ startIndex: currentGroupStartIndex,
120
+ entries: currentGroupEntries
121
+ });
122
+ const childArray = React.Children.toArray(children);
123
+ const dividerChildren = childArray.filter((child) => React.isValidElement(child) && child.type === GroupDivider);
124
+ const itemChildren = childArray.filter((child) => !React.isValidElement(child) || child.type !== GroupDivider);
125
+ return /* @__PURE__ */ jsx(Fragment, { children: groups.map((group, groupIndex) => /* @__PURE__ */ jsx(GroupContext.Provider, {
126
+ value: {
127
+ groupIndex,
128
+ groupLabel: group.label,
129
+ entries: group.entries,
130
+ startIndex: group.startIndex,
131
+ totalEntryCount: entries.length
132
+ },
133
+ children: /* @__PURE__ */ jsxs("div", { children: [dividerChildren, /* @__PURE__ */ jsx("ol", {
134
+ className: cn("m-0 list-none p-0", className),
135
+ start: group.startIndex + 1,
136
+ children: itemChildren
137
+ })] })
138
+ }, `${group.startIndex}-${group.label}`)) });
139
+ }
140
+ function GroupItem({ children, className }) {
141
+ const { entries, startIndex, groupIndex, totalEntryCount } = useGroup();
142
+ const { getKey } = useRanking();
143
+ return /* @__PURE__ */ jsx(Fragment, { children: entries.map((entry, entryIndexInGroup) => {
144
+ const globalIndex = startIndex + entryIndexInGroup;
145
+ const sharedContext = {
146
+ globalIndex,
147
+ groupIndex,
148
+ rank: globalIndex + 1,
149
+ rankInGroup: entryIndexInGroup + 1,
150
+ isFirstInGroup: entryIndexInGroup === 0,
151
+ isLastInGroup: entryIndexInGroup === entries.length - 1,
152
+ isLastItem: globalIndex === totalEntryCount - 1
153
+ };
154
+ if (entry.type === "slot") return /* @__PURE__ */ jsx("li", {
155
+ className,
156
+ children: typeof entry.spec.children === "function" ? entry.spec.children(sharedContext) : entry.spec.children
157
+ }, entry.spec.key);
158
+ const context = {
159
+ item: entry.item,
160
+ ...sharedContext
161
+ };
162
+ return /* @__PURE__ */ jsx(GroupItemContext.Provider, {
163
+ value: context,
164
+ children: /* @__PURE__ */ jsx("li", {
165
+ className,
166
+ children
167
+ })
168
+ }, getKey(entry.item));
169
+ }) });
170
+ }
171
+ function GroupItemIndex({ children, className }) {
172
+ const { globalIndex, rank, groupIndex } = useGroupItem();
173
+ if (children) return /* @__PURE__ */ jsx(Fragment, { children: children({
174
+ globalIndex,
175
+ rank,
176
+ groupIndex
177
+ }) });
178
+ return /* @__PURE__ */ jsxs(Text, {
179
+ color: "tertiary",
180
+ className: cn("w-8 shrink-0", className),
181
+ children: ["#", rank]
182
+ });
183
+ }
184
+ function GroupItemValue({ children }) {
185
+ const groupItemContext = useGroupItem();
186
+ return /* @__PURE__ */ jsx(Fragment, { children: children(groupItemContext.item, groupItemContext) });
187
+ }
188
+ function GroupDivider({ children, className }) {
189
+ const { groupLabel, groupIndex } = useGroup();
190
+ if (children) return /* @__PURE__ */ jsx("div", {
191
+ "data-ranking-group-divider": true,
192
+ className: cn("sticky top-0 bg-background", className),
193
+ style: { zIndex: 10 + groupIndex },
194
+ children: children({
195
+ label: groupLabel,
196
+ groupIndex
197
+ })
198
+ });
199
+ return /* @__PURE__ */ jsx("div", {
200
+ "data-ranking-group-divider": true,
201
+ className: cn("sticky top-0 bg-background", className),
202
+ style: { zIndex: 10 + groupIndex },
203
+ children: /* @__PURE__ */ jsx(Separator, { label: groupLabel })
204
+ });
205
+ }
206
+ const Ranking = {
207
+ Root: RankingRoot,
208
+ Empty,
209
+ Slot,
210
+ Group,
211
+ GroupItem,
212
+ GroupItemIndex,
213
+ GroupItemValue,
214
+ GroupDivider
215
+ };
216
+ const RankedList = Ranking;
217
+
218
+ //#endregion
219
+ export { RankedList, Ranking };
@@ -0,0 +1 @@
1
+ import { GroupItemContextValue, RankedList, RankedListProps, Ranking, RankingProps, SlotContext, SlotProps } from "./Ranking.js";
@@ -0,0 +1,20 @@
1
+ //#region src/hooks/useCountdown.d.ts
2
+ interface UseCountdownOptions {
3
+ /** Stop updating when countdown reaches zero (default: false - keeps counting up) */
4
+ stopOnExpired?: boolean;
5
+ }
6
+ interface UseCountdownResult {
7
+ timeString: string | null;
8
+ remainingMs: number | null;
9
+ isExpired: boolean;
10
+ }
11
+ /**
12
+ * Returns countdown state that updates every second via requestAnimationFrame.
13
+ * Only re-renders when the seconds value changes to minimize layout shift.
14
+ *
15
+ * @param to - Target date to count down to (null disables the countdown)
16
+ * @returns Object with formatted timeString, remainingMs, and isExpired flag
17
+ */
18
+ declare function useCountdown(to: Date | null, options?: UseCountdownOptions): UseCountdownResult;
19
+ //#endregion
20
+ export { UseCountdownResult, useCountdown };
@@ -0,0 +1,75 @@
1
+ "use client";
2
+
3
+ import { formatCountdownString } from "../utils/format.js";
4
+ import { useLayoutEffect, useState } from "react";
5
+
6
+ //#region src/hooks/useCountdown.ts
7
+ /**
8
+ * Returns countdown state that updates every second via requestAnimationFrame.
9
+ * Only re-renders when the seconds value changes to minimize layout shift.
10
+ *
11
+ * @param to - Target date to count down to (null disables the countdown)
12
+ * @returns Object with formatted timeString, remainingMs, and isExpired flag
13
+ */
14
+ function useCountdown(to, options) {
15
+ const { stopOnExpired = false } = options ?? {};
16
+ const [result, setResult] = useState(() => {
17
+ if (!to) return {
18
+ timeString: null,
19
+ remainingMs: null,
20
+ isExpired: false
21
+ };
22
+ const remainingMs = to.getTime() - Date.now();
23
+ return {
24
+ timeString: formatCountdownString(remainingMs),
25
+ remainingMs,
26
+ isExpired: remainingMs <= 0
27
+ };
28
+ });
29
+ useLayoutEffect(() => {
30
+ if (!to) {
31
+ setResult({
32
+ timeString: null,
33
+ remainingMs: null,
34
+ isExpired: false
35
+ });
36
+ return;
37
+ }
38
+ const target = to.getTime();
39
+ const initialRemainingMs = target - Date.now();
40
+ setResult({
41
+ timeString: formatCountdownString(initialRemainingMs),
42
+ remainingMs: initialRemainingMs,
43
+ isExpired: initialRemainingMs <= 0
44
+ });
45
+ let lastSeconds = Math.floor(Math.abs(initialRemainingMs) / 1e3);
46
+ let hasExpired = initialRemainingMs <= 0;
47
+ let frameId;
48
+ const tick = () => {
49
+ const remainingMs = target - Date.now();
50
+ const absMs = Math.abs(remainingMs);
51
+ const isExpired = remainingMs <= 0;
52
+ if (stopOnExpired && hasExpired) {
53
+ frameId = requestAnimationFrame(tick);
54
+ return;
55
+ }
56
+ if (isExpired) hasExpired = true;
57
+ const currentSeconds = Math.floor(absMs / 1e3);
58
+ if (currentSeconds !== lastSeconds || isExpired && lastSeconds !== -2) {
59
+ lastSeconds = isExpired ? -2 : currentSeconds;
60
+ setResult({
61
+ timeString: formatCountdownString(remainingMs),
62
+ remainingMs,
63
+ isExpired
64
+ });
65
+ }
66
+ frameId = requestAnimationFrame(tick);
67
+ };
68
+ frameId = requestAnimationFrame(tick);
69
+ return () => cancelAnimationFrame(frameId);
70
+ }, [to, stopOnExpired]);
71
+ return result;
72
+ }
73
+
74
+ //#endregion
75
+ export { useCountdown };
@@ -0,0 +1,36 @@
1
+ import { AuctionBid, AuctionBidStatus, AuctionBidder, AuctionCallbacks, AuctionData, AuctionFormatters, AuctionTickConfig, AuctionUserBid, OperationState, OperationStatus, RankableBid } from "./types/index.js";
2
+ import { AuctionProvider, AuctionProviderProps, useAuctionContext } from "./components/blocks/auction/AuctionContext.js";
3
+ import { Auction, AuctionProps } from "./components/blocks/auction/Auction.js";
4
+ import { FramedImage, FramedImageProps } from "./components/primitives/framed-image/FramedImage.js";
5
+ import { AuctionBidForm } from "./components/blocks/auction/AuctionBidForm.js";
6
+ import { AuctionBidInput, AuctionBidInputProps } from "./components/blocks/auction/AuctionBidInput.js";
7
+ import { AuctionInfo, AuctionInfoProps } from "./components/blocks/auction/AuctionInfo.js";
8
+ import { AuctionBiddingPanel, AuctionBiddingPanelProps, AuctionDetails, AuctionDetailsBody, AuctionDetailsBodyProps, AuctionDetailsFooter, AuctionDetailsFooterProps, AuctionDetailsHeader, AuctionDetailsHeaderProps, AuctionDetailsProps, AuctionLayout, AuctionLayoutProps, AuctionRankingsContainer, AuctionRankingsContainerProps } from "./components/blocks/auction/AuctionLayout.js";
9
+ import { Button, ButtonElement, ButtonProps, buttonVariants } from "./components/primitives/Button.js";
10
+ import { useCountdown } from "./hooks/useCountdown.js";
11
+ import { Countdown, CountdownProps } from "./components/primitives/countdown/Countdown.js";
12
+ import { Drawer, DrawerProps } from "./components/primitives/Drawer.js";
13
+ import { Feedback } from "./components/primitives/Feedback.js";
14
+ import { MorphDialog, MorphDialogProps } from "./components/primitives/MorphDialog.js";
15
+ import { FormatPriceOptions, Price, PriceProps, PriceSymbolProps, PriceValueProps, formatPrice } from "./components/primitives/Price.js";
16
+ import { CursorGrowIcon, SteppedInput } from "./components/primitives/SteppedInput.js";
17
+ import { PriceInput } from "./components/primitives/PriceInput.js";
18
+ import { Separator } from "./components/primitives/Separator.js";
19
+ import { Receipt, ReceiptDiscountProps, ReceiptFeeProps, ReceiptFooterProps, ReceiptHeaderProps, ReceiptItemProps, ReceiptPriceProps, ReceiptProps, ReceiptSeparatorProps, ReceiptSubtotalProps, ReceiptTaxProps, ReceiptTotalProps } from "./components/primitives/Receipt.js";
20
+ import { GroupItemContextValue, RankedList, RankedListProps, Ranking, RankingProps, SlotContext, SlotProps } from "./components/primitives/ranked-list/Ranking.js";
21
+ import { Scale, ScaleValue, SnapMode, TickContext, useScale } from "./components/primitives/Scale.js";
22
+ import { Skeleton, SkeletonElement, SkeletonProps } from "./components/primitives/Skeleton.js";
23
+ import { Tab, Tabs, TabsContextType, TabsIndicator, TabsList, TabsPanel } from "./components/primitives/Tabs.js";
24
+ import { Text, TextElement, TextProps, textVariants } from "./components/primitives/Text.js";
25
+ import { Tag, TagElement, TagProps } from "./components/primitives/Tag.js";
26
+ import { AuctionRankings, AuctionRankingsProps, RankingsSkeleton } from "./components/blocks/auction/AuctionRankings.js";
27
+ import { AuctionStatusTag, AuctionStatusTagProps } from "./components/blocks/auction/AuctionStatusTag.js";
28
+ import { AuctionSuggestedBids, AuctionSuggestedBidsProps, SuggestedBidContextValue, useSuggestedBid } from "./components/blocks/auction/AuctionSuggestedBids.js";
29
+ import { AuctionYourBidCard, AuctionYourBidCardProps } from "./components/blocks/auction/AuctionYourBidCard.js";
30
+ import { AuctionYourBids, AuctionYourBidsProps } from "./components/blocks/auction/AuctionYourBids.js";
31
+ import { cn } from "./lib/cn.js";
32
+ import { springs, transitions } from "./lib/motion.js";
33
+ import { formatCountdownString, formatDateTime, formatFullTimestamp, formatShortDate, formatShortRelative, formatWeiToEth, parseEthToWei } from "./utils/format.js";
34
+ import { getActiveTickSize, isValidTickPrice, roundDownToValidBid } from "./utils/tick-validation.js";
35
+ import { getProjectedRankForPrice, getSuggestedBidPrices } from "./utils/rank-utils.js";
36
+ export { Auction, FramedImage as AuctionArtwork, type FramedImageProps as AuctionArtworkProps, AuctionBid, AuctionBidForm, AuctionBidInput, type AuctionBidInputProps, AuctionBidStatus, AuctionBidder, AuctionBiddingPanel, type AuctionBiddingPanelProps, AuctionCallbacks, AuctionData, AuctionDetails, AuctionDetailsBody, type AuctionDetailsBodyProps, AuctionDetailsFooter, type AuctionDetailsFooterProps, AuctionDetailsHeader, type AuctionDetailsHeaderProps, type AuctionDetailsProps, AuctionFormatters, AuctionInfo, type AuctionInfoProps, AuctionLayout, type AuctionLayoutProps, type AuctionProps, AuctionProvider, type AuctionProviderProps, AuctionRankings, AuctionRankingsContainer, type AuctionRankingsContainerProps, type AuctionRankingsProps, AuctionStatusTag, type AuctionStatusTagProps, AuctionSuggestedBids, type AuctionSuggestedBidsProps, AuctionTickConfig, AuctionUserBid, AuctionYourBidCard, type AuctionYourBidCardProps, AuctionYourBids, type AuctionYourBidsProps, Button, type ButtonElement, type ButtonProps, Countdown, CountdownProps, CursorGrowIcon, Drawer, type DrawerProps, Feedback, type FormatPriceOptions, FramedImage, type FramedImageProps, GroupItemContextValue, MorphDialog, type MorphDialogProps, OperationState, OperationStatus, Price, PriceInput, type PriceProps, type PriceSymbolProps, type PriceValueProps, RankableBid, RankedList, RankedListProps, Ranking, RankingProps, RankingsSkeleton, Receipt, type ReceiptDiscountProps, type ReceiptFeeProps, type ReceiptFooterProps, type ReceiptHeaderProps, type ReceiptItemProps, type ReceiptPriceProps, type ReceiptProps, type ReceiptSeparatorProps, type ReceiptSubtotalProps, type ReceiptTaxProps, type ReceiptTotalProps, Scale, type TickContext as ScaleTickContext, type ScaleValue, Separator, Skeleton, type SkeletonElement, type SkeletonProps, SlotContext, SlotProps, type SnapMode, SteppedInput, type SuggestedBidContextValue, Tab, Tabs, type TabsContextType, TabsIndicator, TabsList, TabsPanel, Tag, type TagElement, type TagProps, Text, type TextElement, type TextProps, buttonVariants, cn, formatCountdownString, formatDateTime, formatFullTimestamp, formatPrice, formatShortDate, formatShortRelative, formatWeiToEth, getActiveTickSize, getProjectedRankForPrice, getSuggestedBidPrices, isValidTickPrice, parseEthToWei, roundDownToValidBid, springs, textVariants, transitions, useAuctionContext, useCountdown, useScale, useSuggestedBid };
package/dist/index.js ADDED
@@ -0,0 +1,36 @@
1
+ import { formatCountdownString, formatDateTime, formatFullTimestamp, formatShortDate, formatShortRelative, formatWeiToEth, parseEthToWei } from "./utils/format.js";
2
+ import { getActiveTickSize, isValidTickPrice, roundDownToValidBid } from "./utils/tick-validation.js";
3
+ import { getProjectedRankForPrice, getSuggestedBidPrices } from "./utils/rank-utils.js";
4
+ import { AuctionProvider, useAuctionContext } from "./components/blocks/auction/AuctionContext.js";
5
+ import { Auction } from "./components/blocks/auction/Auction.js";
6
+ import { cn } from "./lib/cn.js";
7
+ import { springs, transitions } from "./lib/motion.js";
8
+ import { MorphDialog } from "./components/primitives/MorphDialog.js";
9
+ import { FramedImage } from "./components/primitives/framed-image/FramedImage.js";
10
+ import { Button, buttonVariants } from "./components/primitives/Button.js";
11
+ import { useCountdown } from "./hooks/useCountdown.js";
12
+ import { Countdown } from "./components/primitives/countdown/Countdown.js";
13
+ import { Drawer } from "./components/primitives/Drawer.js";
14
+ import { Feedback } from "./components/primitives/Feedback.js";
15
+ import { Price, formatPrice } from "./components/primitives/Price.js";
16
+ import { CursorGrowIcon, SteppedInput } from "./components/primitives/SteppedInput.js";
17
+ import { PriceInput } from "./components/primitives/PriceInput.js";
18
+ import { Text, textVariants } from "./components/primitives/Text.js";
19
+ import { Separator } from "./components/primitives/Separator.js";
20
+ import { Receipt } from "./components/primitives/Receipt.js";
21
+ import { RankedList, Ranking } from "./components/primitives/ranked-list/Ranking.js";
22
+ import { Scale, useScale } from "./components/primitives/Scale.js";
23
+ import { Skeleton } from "./components/primitives/Skeleton.js";
24
+ import { Tab, Tabs, TabsIndicator, TabsList, TabsPanel } from "./components/primitives/Tabs.js";
25
+ import { Tag } from "./components/primitives/Tag.js";
26
+ import { AuctionBidForm } from "./components/blocks/auction/AuctionBidForm.js";
27
+ import { AuctionBidInput } from "./components/blocks/auction/AuctionBidInput.js";
28
+ import { AuctionStatusTag } from "./components/blocks/auction/AuctionStatusTag.js";
29
+ import { AuctionInfo } from "./components/blocks/auction/AuctionInfo.js";
30
+ import { AuctionBiddingPanel, AuctionDetails, AuctionDetailsBody, AuctionDetailsFooter, AuctionDetailsHeader, AuctionLayout, AuctionRankingsContainer } from "./components/blocks/auction/AuctionLayout.js";
31
+ import { AuctionRankings, RankingsSkeleton } from "./components/blocks/auction/AuctionRankings.js";
32
+ import { AuctionSuggestedBids, useSuggestedBid } from "./components/blocks/auction/AuctionSuggestedBids.js";
33
+ import { AuctionYourBidCard } from "./components/blocks/auction/AuctionYourBidCard.js";
34
+ import { AuctionYourBids } from "./components/blocks/auction/AuctionYourBids.js";
35
+
36
+ export { Auction, FramedImage as AuctionArtwork, AuctionBidForm, AuctionBidInput, AuctionBiddingPanel, AuctionDetails, AuctionDetailsBody, AuctionDetailsFooter, AuctionDetailsHeader, AuctionInfo, AuctionLayout, AuctionProvider, AuctionRankings, AuctionRankingsContainer, AuctionStatusTag, AuctionSuggestedBids, AuctionYourBidCard, AuctionYourBids, Button, Countdown, CursorGrowIcon, Drawer, Feedback, FramedImage, MorphDialog, Price, PriceInput, RankedList, Ranking, RankingsSkeleton, Receipt, Scale, Separator, Skeleton, SteppedInput, Tab, Tabs, TabsIndicator, TabsList, TabsPanel, Tag, Text, buttonVariants, cn, formatCountdownString, formatDateTime, formatFullTimestamp, formatPrice, formatShortDate, formatShortRelative, formatWeiToEth, getActiveTickSize, getProjectedRankForPrice, getSuggestedBidPrices, isValidTickPrice, parseEthToWei, roundDownToValidBid, springs, textVariants, transitions, useAuctionContext, useCountdown, useScale, useSuggestedBid };
@@ -0,0 +1,6 @@
1
+ import { ClassValue } from "clsx";
2
+
3
+ //#region src/lib/cn.d.ts
4
+ declare function cn(...inputs: ClassValue[]): string;
5
+ //#endregion
6
+ export { cn };