casino-ui 0.1.0

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 (196) hide show
  1. package/README.md +213 -0
  2. package/dist/assets/assets/card-back.svg +43 -0
  3. package/dist/assets/assets/card-shoe-overlay.svg +14 -0
  4. package/dist/assets/card-back.svg +43 -0
  5. package/dist/assets/card-shoe-overlay.svg +14 -0
  6. package/dist/casino-ui.css +2 -0
  7. package/dist/components/bet-panel.d.ts +41 -0
  8. package/dist/components/bet-panel.d.ts.map +1 -0
  9. package/dist/components/bet-panel.js +37 -0
  10. package/dist/components/bet-panel.js.map +1 -0
  11. package/dist/components/button.d.ts +15 -0
  12. package/dist/components/button.d.ts.map +1 -0
  13. package/dist/components/button.js +27 -0
  14. package/dist/components/button.js.map +1 -0
  15. package/dist/components/card-score-badge.d.ts +9 -0
  16. package/dist/components/card-score-badge.d.ts.map +1 -0
  17. package/dist/components/card-score-badge.js +20 -0
  18. package/dist/components/card-score-badge.js.map +1 -0
  19. package/dist/components/card-shoe.d.ts +6 -0
  20. package/dist/components/card-shoe.d.ts.map +1 -0
  21. package/dist/components/card-shoe.js +14 -0
  22. package/dist/components/card-shoe.js.map +1 -0
  23. package/dist/components/card-table.d.ts +7 -0
  24. package/dist/components/card-table.d.ts.map +1 -0
  25. package/dist/components/card-table.js +6 -0
  26. package/dist/components/card-table.js.map +1 -0
  27. package/dist/components/chip-rack.d.ts +6 -0
  28. package/dist/components/chip-rack.d.ts.map +1 -0
  29. package/dist/components/chip-rack.js +13 -0
  30. package/dist/components/chip-rack.js.map +1 -0
  31. package/dist/components/chip.d.ts +49 -0
  32. package/dist/components/chip.d.ts.map +1 -0
  33. package/dist/components/chip.js +81 -0
  34. package/dist/components/chip.js.map +1 -0
  35. package/dist/components/game-footer.d.ts +29 -0
  36. package/dist/components/game-footer.d.ts.map +1 -0
  37. package/dist/components/game-footer.js +72 -0
  38. package/dist/components/game-footer.js.map +1 -0
  39. package/dist/components/game-info-dialog.d.ts +23 -0
  40. package/dist/components/game-info-dialog.d.ts.map +1 -0
  41. package/dist/components/game-info-dialog.js +26 -0
  42. package/dist/components/game-info-dialog.js.map +1 -0
  43. package/dist/components/icon.d.ts +10 -0
  44. package/dist/components/icon.d.ts.map +1 -0
  45. package/dist/components/icon.js +59 -0
  46. package/dist/components/icon.js.map +1 -0
  47. package/dist/components/poker-card.d.ts +15 -0
  48. package/dist/components/poker-card.d.ts.map +1 -0
  49. package/dist/components/poker-card.js +77 -0
  50. package/dist/components/poker-card.js.map +1 -0
  51. package/dist/components/result-badge.d.ts +14 -0
  52. package/dist/components/result-badge.d.ts.map +1 -0
  53. package/dist/components/result-badge.js +71 -0
  54. package/dist/components/result-badge.js.map +1 -0
  55. package/dist/components/switch-table-dialog.d.ts +10 -0
  56. package/dist/components/switch-table-dialog.d.ts.map +1 -0
  57. package/dist/components/switch-table-dialog.js +51 -0
  58. package/dist/components/switch-table-dialog.js.map +1 -0
  59. package/dist/components/toast-container.d.ts +8 -0
  60. package/dist/components/toast-container.d.ts.map +1 -0
  61. package/dist/components/toast-container.js +8 -0
  62. package/dist/components/toast-container.js.map +1 -0
  63. package/dist/components/toast-helpers.d.ts +22 -0
  64. package/dist/components/toast-helpers.d.ts.map +1 -0
  65. package/dist/components/toast-helpers.js +47 -0
  66. package/dist/components/toast-helpers.js.map +1 -0
  67. package/dist/components/toast.d.ts +26 -0
  68. package/dist/components/toast.d.ts.map +1 -0
  69. package/dist/components/toast.js +49 -0
  70. package/dist/components/toast.js.map +1 -0
  71. package/dist/components/ui/dialog.d.ts +14 -0
  72. package/dist/components/ui/dialog.d.ts.map +1 -0
  73. package/dist/components/ui/dialog.js +35 -0
  74. package/dist/components/ui/dialog.js.map +1 -0
  75. package/dist/components/ui/drawer.d.ts +14 -0
  76. package/dist/components/ui/drawer.d.ts.map +1 -0
  77. package/dist/components/ui/drawer.js +35 -0
  78. package/dist/components/ui/drawer.js.map +1 -0
  79. package/dist/components/ui/dropdown-menu.d.ts +27 -0
  80. package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
  81. package/dist/components/ui/dropdown-menu.js +39 -0
  82. package/dist/components/ui/dropdown-menu.js.map +1 -0
  83. package/dist/index.d.ts +23 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +25 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/lib/utils.d.ts +3 -0
  88. package/dist/lib/utils.d.ts.map +1 -0
  89. package/dist/lib/utils.js +6 -0
  90. package/dist/lib/utils.js.map +1 -0
  91. package/dist/stories/BetPanel.stories.d.ts +10 -0
  92. package/dist/stories/BetPanel.stories.d.ts.map +1 -0
  93. package/dist/stories/BetPanel.stories.js +34 -0
  94. package/dist/stories/BetPanel.stories.js.map +1 -0
  95. package/dist/stories/Button.stories.d.ts +13 -0
  96. package/dist/stories/Button.stories.d.ts.map +1 -0
  97. package/dist/stories/Button.stories.js +39 -0
  98. package/dist/stories/Button.stories.js.map +1 -0
  99. package/dist/stories/CardScoreBadge.stories.d.ts +8 -0
  100. package/dist/stories/CardScoreBadge.stories.d.ts.map +1 -0
  101. package/dist/stories/CardScoreBadge.stories.js +21 -0
  102. package/dist/stories/CardScoreBadge.stories.js.map +1 -0
  103. package/dist/stories/CardShoe.stories.d.ts +7 -0
  104. package/dist/stories/CardShoe.stories.d.ts.map +1 -0
  105. package/dist/stories/CardShoe.stories.js +8 -0
  106. package/dist/stories/CardShoe.stories.js.map +1 -0
  107. package/dist/stories/CardTable.stories.d.ts +7 -0
  108. package/dist/stories/CardTable.stories.d.ts.map +1 -0
  109. package/dist/stories/CardTable.stories.js +15 -0
  110. package/dist/stories/CardTable.stories.js.map +1 -0
  111. package/dist/stories/Chip.stories.d.ts +11 -0
  112. package/dist/stories/Chip.stories.d.ts.map +1 -0
  113. package/dist/stories/Chip.stories.js +32 -0
  114. package/dist/stories/Chip.stories.js.map +1 -0
  115. package/dist/stories/ChipRack.stories.d.ts +7 -0
  116. package/dist/stories/ChipRack.stories.d.ts.map +1 -0
  117. package/dist/stories/ChipRack.stories.js +8 -0
  118. package/dist/stories/ChipRack.stories.js.map +1 -0
  119. package/dist/stories/Dialog.stories.d.ts +6 -0
  120. package/dist/stories/Dialog.stories.d.ts.map +1 -0
  121. package/dist/stories/Dialog.stories.js +15 -0
  122. package/dist/stories/Dialog.stories.js.map +1 -0
  123. package/dist/stories/GameFooter.stories.d.ts +7 -0
  124. package/dist/stories/GameFooter.stories.d.ts.map +1 -0
  125. package/dist/stories/GameFooter.stories.js +37 -0
  126. package/dist/stories/GameFooter.stories.js.map +1 -0
  127. package/dist/stories/Icon.stories.d.ts +9 -0
  128. package/dist/stories/Icon.stories.d.ts.map +1 -0
  129. package/dist/stories/Icon.stories.js +27 -0
  130. package/dist/stories/Icon.stories.js.map +1 -0
  131. package/dist/stories/PokerCard.stories.d.ts +14 -0
  132. package/dist/stories/PokerCard.stories.d.ts.map +1 -0
  133. package/dist/stories/PokerCard.stories.js +40 -0
  134. package/dist/stories/PokerCard.stories.js.map +1 -0
  135. package/dist/stories/ResultBadge.stories.d.ts +11 -0
  136. package/dist/stories/ResultBadge.stories.d.ts.map +1 -0
  137. package/dist/stories/ResultBadge.stories.js +32 -0
  138. package/dist/stories/ResultBadge.stories.js.map +1 -0
  139. package/dist/stories/Toast.stories.d.ts +10 -0
  140. package/dist/stories/Toast.stories.d.ts.map +1 -0
  141. package/dist/stories/Toast.stories.js +34 -0
  142. package/dist/stories/Toast.stories.js.map +1 -0
  143. package/dist/styles/casino-ui-base.css +310 -0
  144. package/dist/styles/styles/casino-ui-base.css +310 -0
  145. package/dist/styles/styles/toast.css +52 -0
  146. package/dist/styles/toast.css +52 -0
  147. package/dist/toast.css +52 -0
  148. package/dist/types.d.ts +11 -0
  149. package/dist/types.d.ts.map +1 -0
  150. package/dist/types.js +2 -0
  151. package/dist/types.js.map +1 -0
  152. package/dist/utils/format-amount.d.ts +2 -0
  153. package/dist/utils/format-amount.d.ts.map +1 -0
  154. package/dist/utils/format-amount.js +31 -0
  155. package/dist/utils/format-amount.js.map +1 -0
  156. package/package.json +58 -0
  157. package/src/assets/card-back.svg +43 -0
  158. package/src/assets/card-shoe-overlay.svg +14 -0
  159. package/src/components/bet-panel.tsx +275 -0
  160. package/src/components/button.tsx +80 -0
  161. package/src/components/card-score-badge.tsx +61 -0
  162. package/src/components/card-shoe.tsx +52 -0
  163. package/src/components/card-table.tsx +182 -0
  164. package/src/components/chip-rack.tsx +55 -0
  165. package/src/components/chip.tsx +203 -0
  166. package/src/components/game-footer.tsx +356 -0
  167. package/src/components/game-info-dialog.tsx +245 -0
  168. package/src/components/icon.tsx +94 -0
  169. package/src/components/poker-card.tsx +192 -0
  170. package/src/components/result-badge.tsx +157 -0
  171. package/src/components/switch-table-dialog.tsx +211 -0
  172. package/src/components/toast-container.tsx +25 -0
  173. package/src/components/toast-helpers.ts +79 -0
  174. package/src/components/toast.tsx +282 -0
  175. package/src/components/ui/dialog.tsx +134 -0
  176. package/src/components/ui/drawer.tsx +132 -0
  177. package/src/components/ui/dropdown-menu.tsx +210 -0
  178. package/src/env.d.ts +6 -0
  179. package/src/index.ts +88 -0
  180. package/src/lib/utils.ts +6 -0
  181. package/src/stories/BetPanel.stories.tsx +113 -0
  182. package/src/stories/Button.stories.tsx +55 -0
  183. package/src/stories/CardScoreBadge.stories.tsx +34 -0
  184. package/src/stories/CardShoe.stories.tsx +12 -0
  185. package/src/stories/Chip.stories.tsx +51 -0
  186. package/src/stories/ChipRack.stories.tsx +12 -0
  187. package/src/stories/Dialog.stories.tsx +45 -0
  188. package/src/stories/GameFooter.stories.tsx +45 -0
  189. package/src/stories/Icon.stories.tsx +49 -0
  190. package/src/stories/PokerCard.stories.tsx +72 -0
  191. package/src/stories/ResultBadge.stories.tsx +51 -0
  192. package/src/stories/Toast.stories.tsx +71 -0
  193. package/src/styles/casino-ui-base.css +310 -0
  194. package/src/styles/toast.css +52 -0
  195. package/src/types.ts +11 -0
  196. package/src/utils/format-amount.ts +35 -0
@@ -0,0 +1,210 @@
1
+ import * as React from "react";
2
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
3
+ import { Check, ChevronRight, Circle } from "lucide-react";
4
+
5
+ import { cn } from "../../lib/utils";
6
+
7
+ const DropdownMenu = DropdownMenuPrimitive.Root;
8
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
9
+ const DropdownMenuGroup = DropdownMenuPrimitive.Group;
10
+ const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
11
+ const DropdownMenuSub = DropdownMenuPrimitive.Sub;
12
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
13
+
14
+ function DropdownMenuSubTrigger({
15
+ className,
16
+ inset,
17
+ children,
18
+ ...props
19
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
20
+ inset?: boolean;
21
+ }) {
22
+ return (
23
+ <DropdownMenuPrimitive.SubTrigger
24
+ data-slot="dropdown-menu-sub-trigger"
25
+ className={cn(
26
+ "flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
27
+ inset && "pl-8",
28
+ className,
29
+ )}
30
+ {...props}
31
+ >
32
+ {children}
33
+ <ChevronRight className="ml-auto" />
34
+ </DropdownMenuPrimitive.SubTrigger>
35
+ );
36
+ }
37
+
38
+ function DropdownMenuSubContent({
39
+ className,
40
+ ...props
41
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
42
+ return (
43
+ <DropdownMenuPrimitive.SubContent
44
+ data-slot="dropdown-menu-sub-content"
45
+ className={cn(
46
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
47
+ className,
48
+ )}
49
+ {...props}
50
+ />
51
+ );
52
+ }
53
+
54
+ function DropdownMenuContent({
55
+ className,
56
+ sideOffset = 4,
57
+ container,
58
+ ...props
59
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Content> & {
60
+ container?: HTMLDivElement | null;
61
+ }) {
62
+ return (
63
+ <DropdownMenuPrimitive.Portal container={container ?? undefined}>
64
+ <DropdownMenuPrimitive.Content
65
+ data-slot="dropdown-menu-content"
66
+ sideOffset={sideOffset}
67
+ className={cn(
68
+ "z-50 sm:min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
69
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
70
+ className,
71
+ )}
72
+ {...props}
73
+ />
74
+ </DropdownMenuPrimitive.Portal>
75
+ );
76
+ }
77
+
78
+ function DropdownMenuItem({
79
+ className,
80
+ inset,
81
+ ...props
82
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
83
+ inset?: boolean;
84
+ }) {
85
+ return (
86
+ <DropdownMenuPrimitive.Item
87
+ data-slot="dropdown-menu-item"
88
+ className={cn(
89
+ "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
90
+ inset && "pl-8",
91
+ className,
92
+ )}
93
+ {...props}
94
+ />
95
+ );
96
+ }
97
+
98
+ function DropdownMenuCheckboxItem({
99
+ className,
100
+ children,
101
+ checked,
102
+ ...props
103
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
104
+ return (
105
+ <DropdownMenuPrimitive.CheckboxItem
106
+ data-slot="dropdown-menu-checkbox-item"
107
+ className={cn(
108
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
109
+ className,
110
+ )}
111
+ checked={checked}
112
+ {...props}
113
+ >
114
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
115
+ <DropdownMenuPrimitive.ItemIndicator>
116
+ <Check className="h-4 w-4" />
117
+ </DropdownMenuPrimitive.ItemIndicator>
118
+ </span>
119
+ {children}
120
+ </DropdownMenuPrimitive.CheckboxItem>
121
+ );
122
+ }
123
+
124
+ function DropdownMenuRadioItem({
125
+ className,
126
+ children,
127
+ ...props
128
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
129
+ return (
130
+ <DropdownMenuPrimitive.RadioItem
131
+ data-slot="dropdown-menu-radio-item"
132
+ className={cn(
133
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
134
+ className,
135
+ )}
136
+ {...props}
137
+ >
138
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
139
+ <DropdownMenuPrimitive.ItemIndicator>
140
+ <Circle className="h-2 w-2 fill-current" />
141
+ </DropdownMenuPrimitive.ItemIndicator>
142
+ </span>
143
+ {children}
144
+ </DropdownMenuPrimitive.RadioItem>
145
+ );
146
+ }
147
+
148
+ function DropdownMenuLabel({
149
+ className,
150
+ inset,
151
+ ...props
152
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
153
+ inset?: boolean;
154
+ }) {
155
+ return (
156
+ <DropdownMenuPrimitive.Label
157
+ data-slot="dropdown-menu-label"
158
+ className={cn(
159
+ "px-2 py-1.5 text-sm font-semibold",
160
+ inset && "pl-8",
161
+ className,
162
+ )}
163
+ {...props}
164
+ />
165
+ );
166
+ }
167
+
168
+ function DropdownMenuSeparator({
169
+ className,
170
+ ...props
171
+ }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
172
+ return (
173
+ <DropdownMenuPrimitive.Separator
174
+ data-slot="dropdown-menu-separator"
175
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
176
+ {...props}
177
+ />
178
+ );
179
+ }
180
+
181
+ function DropdownMenuShortcut({
182
+ className,
183
+ ...props
184
+ }: React.HTMLAttributes<HTMLSpanElement>) {
185
+ return (
186
+ <span
187
+ data-slot="dropdown-menu-shortcut"
188
+ className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
189
+ {...props}
190
+ />
191
+ );
192
+ }
193
+
194
+ export {
195
+ DropdownMenu,
196
+ DropdownMenuTrigger,
197
+ DropdownMenuContent,
198
+ DropdownMenuItem,
199
+ DropdownMenuCheckboxItem,
200
+ DropdownMenuRadioItem,
201
+ DropdownMenuLabel,
202
+ DropdownMenuSeparator,
203
+ DropdownMenuShortcut,
204
+ DropdownMenuGroup,
205
+ DropdownMenuPortal,
206
+ DropdownMenuSub,
207
+ DropdownMenuSubContent,
208
+ DropdownMenuSubTrigger,
209
+ DropdownMenuRadioGroup,
210
+ };
package/src/env.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ declare module "*.svg" {
2
+ const content: string;
3
+ export default content;
4
+ }
5
+
6
+ declare module "*.css" {}
package/src/index.ts ADDED
@@ -0,0 +1,88 @@
1
+ // Components
2
+ export { Button, buttonVariants, type ButtonProps } from "./components/button";
3
+ export {
4
+ default as Chip,
5
+ CHIP_PRESETS,
6
+ CHIP_DENOMINATIONS,
7
+ getChipDenominationForAmount,
8
+ type ChipDenomination,
9
+ } from "./components/chip";
10
+ export { ChipRack } from "./components/chip-rack";
11
+ export { PokerCard, type Suit, type Rank } from "./components/poker-card";
12
+ export { CardShoe } from "./components/card-shoe";
13
+ export { default as CardTable } from "./components/card-table";
14
+ export { default as CardScoreBadge } from "./components/card-score-badge";
15
+ export { ResultBadge, type ResultType } from "./components/result-badge";
16
+ export { Icon } from "./components/icon";
17
+ export { GameFooter } from "./components/game-footer";
18
+ export { default as GameInfoDialog } from "./components/game-info-dialog";
19
+ export { default as SwitchTableDialog } from "./components/switch-table-dialog";
20
+ export {
21
+ BetPanelRoot,
22
+ BetPanelInput,
23
+ BetPanelActions,
24
+ BetPanelChips,
25
+ BetPanelTimer,
26
+ BetPanelFoldingInfo,
27
+ } from "./components/bet-panel";
28
+
29
+ // Toast system
30
+ export { CasinoToastContainer } from "./components/toast-container";
31
+ export { toast } from "./components/toast-helpers";
32
+ export type {
33
+ EphemeralVariant,
34
+ StatusVariant,
35
+ ToastAction,
36
+ } from "./components/toast";
37
+
38
+ // Utilities
39
+ export { cn } from "./lib/utils";
40
+ export { formatAmountDirect } from "./utils/format-amount";
41
+
42
+ // Types
43
+ export type { CoinInfo } from "./types";
44
+
45
+ // UI primitives
46
+ export {
47
+ Dialog,
48
+ DialogClose,
49
+ DialogContent,
50
+ DialogDescription,
51
+ DialogFooter,
52
+ DialogHeader,
53
+ DialogOverlay,
54
+ DialogPortal,
55
+ DialogTitle,
56
+ DialogTrigger,
57
+ } from "./components/ui/dialog";
58
+
59
+ export {
60
+ Drawer,
61
+ DrawerPortal,
62
+ DrawerOverlay,
63
+ DrawerTrigger,
64
+ DrawerClose,
65
+ DrawerContent,
66
+ DrawerHeader,
67
+ DrawerFooter,
68
+ DrawerTitle,
69
+ DrawerDescription,
70
+ } from "./components/ui/drawer";
71
+
72
+ export {
73
+ DropdownMenu,
74
+ DropdownMenuTrigger,
75
+ DropdownMenuContent,
76
+ DropdownMenuItem,
77
+ DropdownMenuCheckboxItem,
78
+ DropdownMenuRadioItem,
79
+ DropdownMenuLabel,
80
+ DropdownMenuSeparator,
81
+ DropdownMenuShortcut,
82
+ DropdownMenuGroup,
83
+ DropdownMenuPortal,
84
+ DropdownMenuSub,
85
+ DropdownMenuSubContent,
86
+ DropdownMenuSubTrigger,
87
+ DropdownMenuRadioGroup,
88
+ } from "./components/ui/dropdown-menu";
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,113 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { useState } from "react";
3
+ import {
4
+ BetPanelRoot,
5
+ BetPanelInput,
6
+ BetPanelActions,
7
+ BetPanelChips,
8
+ BetPanelTimer,
9
+ BetPanelFoldingInfo,
10
+ } from "../components/bet-panel";
11
+ import { Button } from "../components/button";
12
+ import Chip, { CHIP_DENOMINATIONS } from "../components/chip";
13
+
14
+ const meta: Meta = {
15
+ title: "Components/BetPanel",
16
+ };
17
+
18
+ export default meta;
19
+ type Story = StoryObj;
20
+
21
+ export const FullBetPanel: Story = {
22
+ render: () => {
23
+ const [value, setValue] = useState("0");
24
+
25
+ return (
26
+ <div className="px-2">
27
+ <BetPanelRoot>
28
+ <div className="flex items-center gap-6 w-full">
29
+ <BetPanelInput
30
+ balance="100.00"
31
+ coinInfo={{ name: "SUI", symbol: "SUI", coinType: "sui/sui", image: "", decimal: 9, factor: 1 }}
32
+ value={value}
33
+ setValue={setValue}
34
+ setOriginalBetSize={() => {}}
35
+ getMaxBet={() => 100}
36
+ setError={() => {}}
37
+ />
38
+ <BetPanelChips>
39
+ {CHIP_DENOMINATIONS.map((denom) => (
40
+ <Chip
41
+ key={denom}
42
+ denomination={denom}
43
+ chipClass="w-8 h-8 md:w-11 md:h-11"
44
+ onClick={() => setValue((Number(value) + denom).toString())}
45
+ isButton
46
+ />
47
+ ))}
48
+ </BetPanelChips>
49
+ <BetPanelActions>
50
+ <Button variant="tertiary">Undo</Button>
51
+ <Button variant="tertiary">Clear</Button>
52
+ <Button variant="primary" className="h-10">Deal Now</Button>
53
+ </BetPanelActions>
54
+ </div>
55
+ </BetPanelRoot>
56
+ </div>
57
+ );
58
+ },
59
+ };
60
+
61
+ export const Timer: Story = {
62
+ render: () => (
63
+ <div style={{ width: 400 }}>
64
+ <BetPanelTimer remainingTime={15} progress={75} isWarning={false} isActive />
65
+ </div>
66
+ ),
67
+ };
68
+
69
+ export const TimerWarning: Story = {
70
+ render: () => (
71
+ <div style={{ width: 400 }}>
72
+ <BetPanelTimer remainingTime={3} progress={15} isWarning isActive />
73
+ </div>
74
+ ),
75
+ };
76
+
77
+ export const FoldingInfo: Story = {
78
+ render: () => {
79
+ const [open, setOpen] = useState(true);
80
+ return (
81
+ <div style={{ width: 400 }} className="bg-panel-bg rounded-xl p-4">
82
+ <Button variant="tertiary" onClick={() => setOpen(!open)} className="mb-2">
83
+ Toggle
84
+ </Button>
85
+ <BetPanelFoldingInfo open={open}>
86
+ <div className="flex items-center justify-center pb-2">
87
+ <span className="text-sm font-semibold text-white">Placing bet...</span>
88
+ </div>
89
+ </BetPanelFoldingInfo>
90
+ </div>
91
+ );
92
+ },
93
+ };
94
+
95
+ export const InputWithError: Story = {
96
+ render: () => {
97
+ const [value, setValue] = useState("999");
98
+ return (
99
+ <div style={{ width: 300 }}>
100
+ <BetPanelInput
101
+ balance="10.00"
102
+ coinInfo={{ name: "SUI", symbol: "SUI", coinType: "sui/sui", image: "", decimal: 9, factor: 1 }}
103
+ value={value}
104
+ setValue={setValue}
105
+ setOriginalBetSize={() => {}}
106
+ getMaxBet={() => 10}
107
+ error="Insufficient balance"
108
+ setError={() => {}}
109
+ />
110
+ </div>
111
+ );
112
+ },
113
+ };
@@ -0,0 +1,55 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Button } from "../components/button";
3
+
4
+ const meta: Meta<typeof Button> = {
5
+ title: "Components/Button",
6
+ component: Button,
7
+ argTypes: {
8
+ variant: {
9
+ control: "select",
10
+ options: ["primary", "secondary", "tertiary", "grey_pure"],
11
+ },
12
+ fullWidth: { control: "boolean" },
13
+ disabled: { control: "boolean" },
14
+ loading: { control: "boolean" },
15
+ },
16
+ };
17
+
18
+ export default meta;
19
+ type Story = StoryObj<typeof Button>;
20
+
21
+ export const Primary: Story = {
22
+ args: { variant: "primary", children: "Deal Now" },
23
+ };
24
+
25
+ export const Secondary: Story = {
26
+ args: { variant: "secondary", children: "Skip" },
27
+ };
28
+
29
+ export const Tertiary: Story = {
30
+ args: { variant: "tertiary", children: "Undo" },
31
+ };
32
+
33
+ export const GreyPure: Story = {
34
+ args: { variant: "grey_pure", children: "Clear" },
35
+ };
36
+
37
+ export const Disabled: Story = {
38
+ args: { variant: "primary", children: "Deal Now", disabled: true },
39
+ };
40
+
41
+ export const FullWidth: Story = {
42
+ args: { variant: "primary", children: "Start Playing", fullWidth: true },
43
+ decorators: [(Story) => <div style={{ width: 300 }}><Story /></div>],
44
+ };
45
+
46
+ export const AllVariants: Story = {
47
+ render: () => (
48
+ <div className="flex flex-col gap-3">
49
+ <Button variant="primary">Primary (Green)</Button>
50
+ <Button variant="secondary">Secondary (Blue)</Button>
51
+ <Button variant="tertiary">Tertiary (Grey)</Button>
52
+ <Button variant="grey_pure">Grey Pure</Button>
53
+ </div>
54
+ ),
55
+ };
@@ -0,0 +1,34 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import CardScoreBadge from "../components/card-score-badge";
3
+
4
+ const meta: Meta<typeof CardScoreBadge> = {
5
+ title: "Components/CardScoreBadge",
6
+ component: CardScoreBadge,
7
+ argTypes: {
8
+ type: {
9
+ control: "select",
10
+ options: ["default", "win", "lose", "bust", "blackjack", "push", "even", "surrender"],
11
+ },
12
+ },
13
+ };
14
+
15
+ export default meta;
16
+ type Story = StoryObj<typeof CardScoreBadge>;
17
+
18
+ export const Default: Story = {
19
+ args: { type: "default", children: "17" },
20
+ decorators: [(Story) => <div className="relative w-20 h-20"><Story /></div>],
21
+ };
22
+
23
+ export const AllTypes: Story = {
24
+ render: () => (
25
+ <div className="flex gap-6">
26
+ {(["default", "win", "lose", "bust", "blackjack", "push", "even", "surrender"] as const).map((type) => (
27
+ <div key={type} className="relative w-16 h-16 flex flex-col items-center">
28
+ <CardScoreBadge type={type}>21</CardScoreBadge>
29
+ <span className="absolute top-2 text-xs text-text-secondary">{type}</span>
30
+ </div>
31
+ ))}
32
+ </div>
33
+ ),
34
+ };
@@ -0,0 +1,12 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { CardShoe } from "../components/card-shoe";
3
+
4
+ const meta: Meta<typeof CardShoe> = {
5
+ title: "Components/CardShoe",
6
+ component: CardShoe,
7
+ };
8
+
9
+ export default meta;
10
+ type Story = StoryObj<typeof CardShoe>;
11
+
12
+ export const Default: Story = {};
@@ -0,0 +1,51 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import Chip, { CHIP_DENOMINATIONS, type ChipDenomination } from "../components/chip";
3
+
4
+ const meta: Meta<typeof Chip> = {
5
+ title: "Components/Chip",
6
+ component: Chip,
7
+ argTypes: {
8
+ denomination: {
9
+ control: "select",
10
+ options: CHIP_DENOMINATIONS,
11
+ },
12
+ isButton: { control: "boolean" },
13
+ selected: { control: "boolean" },
14
+ showText: { control: "boolean" },
15
+ },
16
+ };
17
+
18
+ export default meta;
19
+ type Story = StoryObj<typeof Chip>;
20
+
21
+ export const Default: Story = {
22
+ args: { denomination: 100, isButton: true },
23
+ };
24
+
25
+ export const Selected: Story = {
26
+ args: { denomination: 25, isButton: true, selected: true },
27
+ };
28
+
29
+ export const WithAmount: Story = {
30
+ args: { amount: 42.5, isButton: false },
31
+ };
32
+
33
+ export const AllDenominations: Story = {
34
+ render: () => (
35
+ <div className="flex gap-2 items-end">
36
+ {CHIP_DENOMINATIONS.map((denom) => (
37
+ <Chip key={denom} denomination={denom} isButton showText />
38
+ ))}
39
+ </div>
40
+ ),
41
+ };
42
+
43
+ export const StaticChips: Story = {
44
+ render: () => (
45
+ <div className="flex gap-2">
46
+ {CHIP_DENOMINATIONS.map((denom) => (
47
+ <Chip key={denom} denomination={denom} showText />
48
+ ))}
49
+ </div>
50
+ ),
51
+ };
@@ -0,0 +1,12 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { ChipRack } from "../components/chip-rack";
3
+
4
+ const meta: Meta<typeof ChipRack> = {
5
+ title: "Components/ChipRack",
6
+ component: ChipRack,
7
+ };
8
+
9
+ export default meta;
10
+ type Story = StoryObj<typeof ChipRack>;
11
+
12
+ export const Default: Story = {};
@@ -0,0 +1,45 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { useState } from "react";
3
+ import {
4
+ Dialog,
5
+ DialogContent,
6
+ DialogHeader,
7
+ DialogTitle,
8
+ DialogDescription,
9
+ DialogFooter,
10
+ DialogClose,
11
+ } from "../components/ui/dialog";
12
+ import { Button } from "../components/button";
13
+
14
+ const meta: Meta = {
15
+ title: "Primitives/Dialog",
16
+ };
17
+
18
+ export default meta;
19
+ type Story = StoryObj;
20
+
21
+ export const Default: Story = {
22
+ render: () => {
23
+ const [open, setOpen] = useState(false);
24
+ return (
25
+ <>
26
+ <Button variant="primary" onClick={() => setOpen(true)}>Open Dialog</Button>
27
+ <Dialog open={open} onOpenChange={setOpen}>
28
+ <DialogContent className="w-100 rounded-xl bg-surface-400">
29
+ <DialogHeader className="flex flex-col gap-2 p-6">
30
+ <DialogTitle className="text-2xl font-bold">Dialog Title</DialogTitle>
31
+ <DialogDescription>This is a dialog description.</DialogDescription>
32
+ </DialogHeader>
33
+ <div className="px-6 py-4">
34
+ <p className="text-sm text-text-secondary">Dialog body content goes here.</p>
35
+ </div>
36
+ <DialogFooter className="px-6 pb-6">
37
+ <Button variant="tertiary" onClick={() => setOpen(false)}>Cancel</Button>
38
+ <Button variant="primary" onClick={() => setOpen(false)}>Confirm</Button>
39
+ </DialogFooter>
40
+ </DialogContent>
41
+ </Dialog>
42
+ </>
43
+ );
44
+ },
45
+ };
@@ -0,0 +1,45 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { GameFooter } from "../components/game-footer";
3
+ import { CasinoToastContainer } from "../components/toast-container";
4
+
5
+ const meta: Meta<typeof GameFooter> = {
6
+ title: "Components/GameFooter",
7
+ component: GameFooter,
8
+ decorators: [
9
+ (Story) => (
10
+ <div style={{ width: 900 }}>
11
+ <Story />
12
+ <CasinoToastContainer />
13
+ </div>
14
+ ),
15
+ ],
16
+ };
17
+
18
+ export default meta;
19
+ type Story = StoryObj<typeof GameFooter>;
20
+
21
+ export const Default: Story = {
22
+ args: {
23
+ tableId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
24
+ shareBaseUrl: "https://example.com/blackjack",
25
+ badges: {
26
+ houseEdge: "0.5",
27
+ minBet: "0.1",
28
+ coinInfo: { name: "SUI", symbol: "SUI", coinType: "sui/sui", image: "", decimal: 9, factor: 1 },
29
+ },
30
+ tabsContents: {
31
+ table: <div className="text-white p-4">Table info content</div>,
32
+ howToPlay: <div className="text-white p-4">How to play content</div>,
33
+ balance: <div className="text-white p-4">Balance content</div>,
34
+ },
35
+ volumeSlider: {
36
+ globalVolume: 0.7,
37
+ setGlobalVolume: () => {},
38
+ setPrevVolume: () => {},
39
+ },
40
+ onToggleMute: () => {},
41
+ onJoin: () => {},
42
+ gameTitle: "Blackjack",
43
+ gameDescription: "Classic Blackjack. Play solo or join a multiplayer table.",
44
+ },
45
+ };