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,49 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Icon } from "../components/icon";
3
+
4
+ const ALL_ICONS = [
5
+ "settings", "share", "sit", "switch-seat", "crown", "check-circle",
6
+ "loader", "surrender", "split", "double", "stand", "hit",
7
+ "x", "check", "logout", "sound", "eye", "rules",
8
+ "copy", "info", "user", "wallet", "chevron-down",
9
+ ];
10
+
11
+ const meta: Meta<typeof Icon> = {
12
+ title: "Components/Icon",
13
+ component: Icon,
14
+ argTypes: {
15
+ icon: { control: "select", options: ALL_ICONS },
16
+ color: { control: "color" },
17
+ },
18
+ };
19
+
20
+ export default meta;
21
+ type Story = StoryObj<typeof Icon>;
22
+
23
+ export const Default: Story = {
24
+ args: { icon: "settings", className: "size-6 text-white" },
25
+ };
26
+
27
+ export const AllIcons: Story = {
28
+ render: () => (
29
+ <div className="grid grid-cols-6 gap-4">
30
+ {ALL_ICONS.map((name) => (
31
+ <div key={name} className="flex flex-col items-center gap-2 p-2">
32
+ <Icon icon={name} className="size-6 text-white" />
33
+ <span className="text-xs text-text-secondary">{name}</span>
34
+ </div>
35
+ ))}
36
+ </div>
37
+ ),
38
+ };
39
+
40
+ export const Colored: Story = {
41
+ render: () => (
42
+ <div className="flex gap-4">
43
+ <Icon icon="check" className="size-6 text-accent-success" />
44
+ <Icon icon="x" className="size-6 text-accent-error" />
45
+ <Icon icon="crown" className="size-6 text-accent-yellow" />
46
+ <Icon icon="info" className="size-6 text-btn-blue" />
47
+ </div>
48
+ ),
49
+ };
@@ -0,0 +1,72 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { PokerCard, type Suit, type Rank } from "../components/poker-card";
3
+
4
+ const meta: Meta<typeof PokerCard> = {
5
+ title: "Components/PokerCard",
6
+ component: PokerCard,
7
+ argTypes: {
8
+ suit: { control: "select", options: ["heart", "diamond", "spade", "club"] },
9
+ rank: { control: "select", options: ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"] },
10
+ side: { control: "select", options: ["front", "back"] },
11
+ size: { control: "select", options: ["default", "mobile", "mobile-small", "mobile-seats"] },
12
+ type: { control: "select", options: ["default", "win", "lose", "bust", "blackjack", "push", "even", "surrender"] },
13
+ showShadow: { control: "boolean" },
14
+ },
15
+ };
16
+
17
+ export default meta;
18
+ type Story = StoryObj<typeof PokerCard>;
19
+
20
+ export const AceOfSpades: Story = {
21
+ args: { suit: "spade", rank: "A", side: "front" },
22
+ };
23
+
24
+ export const KingOfHearts: Story = {
25
+ args: { suit: "heart", rank: "K", side: "front" },
26
+ };
27
+
28
+ export const CardBack: Story = {
29
+ args: { side: "back" },
30
+ };
31
+
32
+ export const WinState: Story = {
33
+ args: { suit: "heart", rank: "A", side: "front", type: "win" },
34
+ };
35
+
36
+ export const BlackjackState: Story = {
37
+ args: { suit: "spade", rank: "A", side: "front", type: "blackjack" },
38
+ };
39
+
40
+ export const AllSuits: Story = {
41
+ render: () => (
42
+ <div className="flex gap-3">
43
+ {(["heart", "diamond", "spade", "club"] as Suit[]).map((suit) => (
44
+ <PokerCard key={suit} suit={suit} rank="A" />
45
+ ))}
46
+ </div>
47
+ ),
48
+ };
49
+
50
+ export const AllSizes: Story = {
51
+ render: () => (
52
+ <div className="flex gap-3 items-end">
53
+ <PokerCard suit="spade" rank="K" size="xs" />
54
+ <PokerCard suit="spade" rank="K" size="sm" />
55
+ <PokerCard suit="spade" rank="K" size="md" />
56
+ <PokerCard suit="spade" rank="K" size="lg" />
57
+ </div>
58
+ ),
59
+ };
60
+
61
+ export const ResultTypes: Story = {
62
+ render: () => (
63
+ <div className="flex gap-3">
64
+ {(["default", "win", "lose", "bust", "blackjack", "push"] as const).map((type) => (
65
+ <div key={type} className="flex flex-col items-center gap-1">
66
+ <PokerCard suit="heart" rank="10" type={type} />
67
+ <span className="text-xs text-text-secondary">{type}</span>
68
+ </div>
69
+ ))}
70
+ </div>
71
+ ),
72
+ };
@@ -0,0 +1,51 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { ResultBadge } from "../components/result-badge";
3
+
4
+ const meta: Meta<typeof ResultBadge> = {
5
+ title: "Components/ResultBadge",
6
+ component: ResultBadge,
7
+ argTypes: {
8
+ type: {
9
+ control: "select",
10
+ options: ["win", "lose", "bust", "push", "blackjack", "even", "surrender"],
11
+ },
12
+ showPayout: { control: "boolean" },
13
+ isUSD: { control: "boolean" },
14
+ isMobile: { control: "boolean" },
15
+ },
16
+ };
17
+
18
+ export default meta;
19
+ type Story = StoryObj<typeof ResultBadge>;
20
+
21
+ export const Win: Story = {
22
+ args: { type: "win" },
23
+ };
24
+
25
+ export const Blackjack: Story = {
26
+ args: { type: "blackjack" },
27
+ };
28
+
29
+ export const WithPayout: Story = {
30
+ args: { type: "win", showPayout: true, amount: "2.50", isUSD: true },
31
+ };
32
+
33
+ export const AllResults: Story = {
34
+ render: () => (
35
+ <div className="flex flex-col gap-2">
36
+ {(["win", "lose", "bust", "push", "blackjack", "even", "surrender"] as const).map((type) => (
37
+ <ResultBadge key={type} type={type} />
38
+ ))}
39
+ </div>
40
+ ),
41
+ };
42
+
43
+ export const AllResultsWithPayout: Story = {
44
+ render: () => (
45
+ <div className="flex flex-col gap-2">
46
+ {(["win", "lose", "bust", "push", "blackjack", "even", "surrender"] as const).map((type) => (
47
+ <ResultBadge key={type} type={type} showPayout amount="1.25" isUSD />
48
+ ))}
49
+ </div>
50
+ ),
51
+ };
@@ -0,0 +1,71 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { CasinoToastContainer } from "../components/toast-container";
3
+ import { toast } from "../components/toast-helpers";
4
+ import { Button } from "../components/button";
5
+
6
+ const meta: Meta = {
7
+ title: "Components/Toast",
8
+ decorators: [
9
+ (Story) => (
10
+ <div>
11
+ <Story />
12
+ <CasinoToastContainer position="bottom-right" />
13
+ </div>
14
+ ),
15
+ ],
16
+ };
17
+
18
+ export default meta;
19
+ type Story = StoryObj;
20
+
21
+ export const Info: Story = {
22
+ render: () => (
23
+ <Button variant="tertiary" onClick={() => toast.info("Card dealt to player")}>
24
+ Show Info Toast
25
+ </Button>
26
+ ),
27
+ };
28
+
29
+ export const Success: Story = {
30
+ render: () => (
31
+ <Button variant="primary" onClick={() => toast.success("You win!")}>
32
+ Show Success Toast
33
+ </Button>
34
+ ),
35
+ };
36
+
37
+ export const StatusError: Story = {
38
+ render: () => (
39
+ <Button variant="tertiary" onClick={() => toast.status.error("Insufficient balance", { title: "Error" })}>
40
+ Show Error Toast
41
+ </Button>
42
+ ),
43
+ };
44
+
45
+ export const StatusSuccess: Story = {
46
+ render: () => (
47
+ <Button variant="primary" onClick={() => toast.status.success("Bet placed successfully", { title: "Confirmed" })}>
48
+ Show Status Success
49
+ </Button>
50
+ ),
51
+ };
52
+
53
+ export const ActionToast: Story = {
54
+ render: () => (
55
+ <Button
56
+ variant="secondary"
57
+ onClick={() =>
58
+ toast.action({
59
+ title: "Switch Table?",
60
+ message: "You will leave the current game.",
61
+ actions: [
62
+ { label: "Cancel", onClick: () => {} },
63
+ { label: "Confirm", onClick: () => {}, highlight: true },
64
+ ],
65
+ })
66
+ }
67
+ >
68
+ Show Action Toast
69
+ </Button>
70
+ ),
71
+ };
@@ -0,0 +1,310 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+
4
+ @custom-variant dark (&:is(.dark *));
5
+
6
+ @theme inline {
7
+ --color-background: var(--background);
8
+ --color-foreground: var(--foreground);
9
+ --color-win: #c7fe51;
10
+ --color-brand: #c7fe51;
11
+ --color-brand-light: #caff33;
12
+ --color-brand-dark: #546b22;
13
+ --color-dialog-content: #1a1a1a;
14
+ --color-accent-error: #af1b45;
15
+ --color-accent-success: #00a95d;
16
+ --color-accent-waring: #f1c40f;
17
+ --color-surface-600: #141414;
18
+ --color-surface-500: #1a1a1a;
19
+ --color-surface-450: #1f1f1f;
20
+ --color-surface-400: #252525;
21
+ --color-surface-300: #333333;
22
+ --color-surface-250: #404040;
23
+ --color-surface-200: #4d4d4d;
24
+ --color-surface-650: #0f0f0f;
25
+ --color-text-secondary: #bfbfbf;
26
+ --color-text-tertiary: #8c8c8c;
27
+ --color-card-suit-red: #f24545;
28
+ --color-card-suit-black: #1a1a1a;
29
+ --color-card-border: #bfbfbf;
30
+ --color-card-back-bg: #f24545;
31
+ --color-card-shoe-bg: #2a2a2a;
32
+ --color-card-shoe-border: #4e4e4e;
33
+ --color-button-grey: #3a3a3a;
34
+ --color-accent-pink: #fd135a;
35
+ --color-accent-fun-red: #db375e;
36
+ --color-accent-yellow: #fee061;
37
+ /* Action panel */
38
+ --color-panel-bg: #252525;
39
+ --color-action-hover: #444444;
40
+ --color-action-active: #2a2a2a;
41
+ --color-surrender-to: #2e2e2e;
42
+ --color-timer-end: #00d474;
43
+ /* Primary button — Green */
44
+ --color-btn-green: #b5e74a;
45
+ --color-btn-green-light: #c7fe51;
46
+ /* Primary button — Blue */
47
+ --color-btn-blue: #3fc1ff;
48
+ --color-btn-blue-light: #63d0ff;
49
+ }
50
+
51
+ /* ── Casino Chip ────────────────────────────────────── */
52
+
53
+ @layer components {
54
+ .chip-body {
55
+ position: relative;
56
+ }
57
+ .chip-body::before {
58
+ content: "";
59
+ position: absolute;
60
+ inset: 0;
61
+ border-radius: inherit;
62
+ background: repeating-conic-gradient(
63
+ from 348.75deg,
64
+ #fff 0deg 22.5deg,
65
+ transparent 22.5deg 45deg
66
+ );
67
+ }
68
+
69
+ /* Chip data-slot sizing tokens */
70
+ [data-slot="chip"] {
71
+ width: var(--chip-outer);
72
+ height: calc(var(--chip-outer) + var(--chip-shadow-depth));
73
+ }
74
+
75
+ [data-slot="chip-body"] {
76
+ width: var(--chip-outer);
77
+ height: var(--chip-outer);
78
+ background-color: var(--chip-color);
79
+ box-shadow: 0px var(--chip-shadow-depth) 0px 0px var(--chip-shadow-color);
80
+ }
81
+
82
+ [data-slot="chip-ring"] {
83
+ width: var(--chip-inner);
84
+ height: var(--chip-inner);
85
+ top: var(--chip-inset);
86
+ left: var(--chip-inset);
87
+ }
88
+
89
+ [data-slot="chip-center"] {
90
+ width: var(--chip-center);
91
+ height: var(--chip-center);
92
+ background-color: var(--chip-color);
93
+ padding: var(--chip-padding);
94
+ }
95
+
96
+ [data-slot="chip-text"] {
97
+ font-size: var(--chip-text);
98
+ font-family:
99
+ "SF Pro Display",
100
+ -apple-system,
101
+ BlinkMacSystemFont,
102
+ sans-serif;
103
+ font-weight: 700;
104
+ }
105
+
106
+ [data-slot="chip-selected-ring"] {
107
+ width: calc(var(--chip-outer) + 4px);
108
+ height: calc(var(--chip-outer) + 2px);
109
+ top: -1px;
110
+ }
111
+
112
+ [data-slot="chip"][data-size="sm"] {
113
+ --chip-outer: 36px;
114
+ --chip-inner: 33px;
115
+ --chip-border: 3.74px;
116
+ --chip-center: 28.7px;
117
+ --chip-text: 10.5px;
118
+ --chip-shadow-depth: 2px;
119
+ --chip-inset: 1.6px;
120
+ --chip-padding: 6.2px;
121
+ }
122
+ [data-slot="chip"][data-size="md"] {
123
+ --chip-outer: 44px;
124
+ --chip-inner: 40px;
125
+ --chip-border: 4.566px;
126
+ --chip-center: 35px;
127
+ --chip-text: 12.865px;
128
+ --chip-shadow-depth: 3px;
129
+ --chip-inset: 2px;
130
+ --chip-padding: 7.6px;
131
+ }
132
+ [data-slot="chip"][data-size="lg"] {
133
+ --chip-outer: 52px;
134
+ --chip-inner: 47px;
135
+ --chip-border: 5.4px;
136
+ --chip-center: 41.4px;
137
+ --chip-text: 15.2px;
138
+ --chip-shadow-depth: 4px;
139
+ --chip-inset: 2.4px;
140
+ --chip-padding: 9px;
141
+ }
142
+
143
+ /* Denomination color tokens */
144
+ [data-slot="chip"][data-denomination="1"] {
145
+ --chip-color: #999999;
146
+ --chip-shadow-color: #474747;
147
+ }
148
+ [data-slot="chip"][data-denomination="5"] {
149
+ --chip-color: #db375e;
150
+ --chip-shadow-color: #63171d;
151
+ }
152
+ [data-slot="chip"][data-denomination="10"] {
153
+ --chip-color: #037a4c;
154
+ --chip-shadow-color: #06503f;
155
+ }
156
+ [data-slot="chip"][data-denomination="25"] {
157
+ --chip-color: #f57fe0;
158
+ --chip-shadow-color: #951f9d;
159
+ }
160
+ [data-slot="chip"][data-denomination="50"] {
161
+ --chip-color: #7454f0;
162
+ --chip-shadow-color: #2d268b;
163
+ }
164
+ [data-slot="chip"][data-denomination="100"] {
165
+ --chip-color: #e3b800;
166
+ --chip-shadow-color: #816b0c;
167
+ }
168
+ [data-slot="chip"][data-denomination="500"] {
169
+ --chip-color: #9727b0;
170
+ --chip-shadow-color: #5b187d;
171
+ }
172
+
173
+ /* Hover glow */
174
+ button[data-slot="chip"]::before {
175
+ content: "";
176
+ position: absolute;
177
+ left: 50%;
178
+ top: 0;
179
+ transform: translateX(-50%);
180
+ width: calc(var(--chip-outer) + 10px);
181
+ height: calc(var(--chip-outer) + 6px);
182
+ border-radius: 50%;
183
+ background: radial-gradient(
184
+ ellipse at center,
185
+ rgba(255, 255, 255, 0.35) 0%,
186
+ rgba(255, 255, 255, 0.15) 40%,
187
+ rgba(255, 255, 255, 0) 70%
188
+ );
189
+ pointer-events: none;
190
+ opacity: 0;
191
+ transition: opacity 150ms;
192
+ }
193
+
194
+ button[data-slot="chip"]:hover::before {
195
+ opacity: 1;
196
+ }
197
+
198
+ button[data-slot="chip"]:hover > [data-slot="chip-body"] {
199
+ box-shadow: 0px var(--chip-shadow-depth) 0px 0px var(--chip-shadow-color);
200
+ }
201
+
202
+ /* ── Action Buttons ───────────────────────────────── */
203
+
204
+ .blue-action-button {
205
+ border-color: var(--color-btn-blue);
206
+ background-image: radial-gradient(
207
+ 97.07% 95.3% at 48.09% 47.12%,
208
+ var(--color-btn-blue) 0%,
209
+ var(--color-btn-blue-light) 100%
210
+ );
211
+ box-shadow: 0 4px 1px 0 rgba(255, 255, 255, 0.4) inset;
212
+ }
213
+
214
+ .blue-action-button:hover {
215
+ background-image: radial-gradient(
216
+ 97.07% 95.3% at 48.09% 47.12%,
217
+ #5cf 0%,
218
+ #8ae2ff 100%
219
+ );
220
+ box-shadow:
221
+ 0 0 12px 0 rgba(199, 243, 81, 0.2),
222
+ 0 3px 1px 0 rgba(255, 255, 255, 0.25) inset;
223
+ }
224
+
225
+ .blue-action-button:active {
226
+ border-color: #2ca1dc;
227
+ background-image: radial-gradient(
228
+ 97.07% 95.3% at 48.09% 47.12%,
229
+ #32aeea 0%,
230
+ #4fc0f2 100%
231
+ );
232
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.25) inset;
233
+ }
234
+
235
+ .green-action-button {
236
+ border-color: var(--color-btn-green);
237
+ background-image: radial-gradient(
238
+ 97.07% 95.3% at 48.09% 47.12%,
239
+ var(--color-btn-green) 0%,
240
+ var(--color-btn-green-light) 100%
241
+ );
242
+ box-shadow: 0 4px 1px 0 rgba(255, 255, 255, 0.4) inset;
243
+ }
244
+
245
+ .green-action-button:hover {
246
+ background-image: radial-gradient(
247
+ 97.07% 95.3% at 48.09% 47.12%,
248
+ #c4fb63 0%,
249
+ #d5ff7a 100%
250
+ );
251
+ box-shadow:
252
+ 0 0 12px 0 rgba(199, 243, 81, 0.2),
253
+ 0 3px 1px 0 rgba(255, 255, 255, 0.25) inset;
254
+ }
255
+
256
+ .green-action-button:active {
257
+ border-color: #a9d53f;
258
+ background-image: radial-gradient(
259
+ 97.07% 95.3% at 48.09% 47.12%,
260
+ #a9d53f 0%,
261
+ #bee84f 100%
262
+ );
263
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.25) inset;
264
+ }
265
+
266
+ .grey-action-button {
267
+ position: relative;
268
+ border-color: var(--color-button-grey);
269
+ background-image: radial-gradient(
270
+ 97.07% 95.3% at 48.09% 47.12%,
271
+ #3a3a3a 0%,
272
+ #2e2e2e 100%
273
+ );
274
+ box-shadow: 0 4px 2px 0 rgba(255, 255, 255, 0.05) inset;
275
+ }
276
+
277
+ .grey-action-button:hover {
278
+ border-color: #464646;
279
+ background-image: radial-gradient(
280
+ 97.07% 95.3% at 48.09% 47.12%,
281
+ #464646 0%,
282
+ #383838 100%
283
+ );
284
+ box-shadow:
285
+ 0 0 8px 0 rgba(255, 255, 255, 0.03),
286
+ 0 3px 2px 0 rgba(255, 255, 255, 0.03) inset;
287
+ }
288
+
289
+ .grey-action-button:active {
290
+ border-color: #2e2e2e;
291
+ background-image: radial-gradient(
292
+ 97.07% 95.3% at 48.09% 47.12%,
293
+ #2e2e2e 0%,
294
+ #262626 100%
295
+ );
296
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.25) inset;
297
+ }
298
+ }
299
+
300
+ /* ── Utilities ──────────────────────────────────────── */
301
+
302
+ @layer utilities {
303
+ .hide-scrollbar::-webkit-scrollbar {
304
+ display: none;
305
+ }
306
+ .hide-scrollbar {
307
+ -ms-overflow-style: none;
308
+ scrollbar-width: none;
309
+ }
310
+ }
@@ -0,0 +1,52 @@
1
+ /*
2
+ * Casino Toast — CSS variable contract + react-toastify overrides
3
+ *
4
+ * All variables have hardcoded fallbacks so toasts render correctly
5
+ * without a host theme. Consumers override variables on .casino-toast
6
+ * or any ancestor to re-theme.
7
+ */
8
+
9
+ .casino-toast {
10
+ --toast-bg: #1f1f1f;
11
+ --toast-border: rgba(255, 255, 255, 0.04);
12
+ --toast-radius: 12px;
13
+ --toast-shadow: 0px 6px 15px -3px rgba(0, 0, 0, 0.15);
14
+ --toast-text-primary: #ffffff;
15
+ --toast-text-secondary: #bfbfbf;
16
+ --toast-icon-info: #3fc1ff;
17
+ --toast-icon-success: #00a95d;
18
+ --toast-icon-warning: #af1b45;
19
+ --toast-icon-error: #af1b45;
20
+ --toast-action-highlight: #9fcc41;
21
+ }
22
+
23
+ /* ── Strip react-toastify default chrome ─────────────── */
24
+
25
+ .casino-toast .Toastify__toast-container {
26
+ padding: 0;
27
+ width: auto;
28
+ }
29
+
30
+ .casino-toast .Toastify__toast {
31
+ background: transparent;
32
+ box-shadow: none;
33
+ padding: 0;
34
+ margin-bottom: 8px;
35
+ min-height: unset;
36
+ border-radius: 0;
37
+ font-family: inherit;
38
+ cursor: default;
39
+ }
40
+
41
+ .casino-toast .Toastify__toast-body {
42
+ padding: 0;
43
+ margin: 0;
44
+ }
45
+
46
+ .casino-toast .Toastify__close-button {
47
+ display: none;
48
+ }
49
+
50
+ .casino-toast .Toastify__toast-icon {
51
+ display: none;
52
+ }
package/src/types.ts ADDED
@@ -0,0 +1,11 @@
1
+ import type React from "react";
2
+
3
+ export type CoinInfo = {
4
+ name: string;
5
+ symbol: string;
6
+ coinType: string;
7
+ image: string | React.ReactNode;
8
+ decimal: number;
9
+ factor: number;
10
+ iconUrl?: string | null;
11
+ };
@@ -0,0 +1,35 @@
1
+ export function formatAmountDirect(amount?: number | string | null): string {
2
+ if (typeof amount === "undefined" || amount === null) {
3
+ return "--";
4
+ }
5
+
6
+ const num = typeof amount === "string" ? parseFloat(amount) : amount;
7
+
8
+ if (isNaN(num)) {
9
+ return "--";
10
+ }
11
+
12
+ const absNum = Math.abs(num);
13
+ let displayValue = num;
14
+ let postfix = "";
15
+
16
+ if (absNum >= 1_000_000_000) {
17
+ displayValue = displayValue / 1_000_000_000;
18
+ postfix = "ʙ";
19
+ } else if (absNum >= 1_000_000) {
20
+ displayValue = displayValue / 1_000_000;
21
+ postfix = "ᴍ";
22
+ } else if (absNum >= 1_000) {
23
+ displayValue = displayValue / 1_000;
24
+ postfix = "ᴋ";
25
+ }
26
+
27
+ const formatted =
28
+ absNum >= 1
29
+ ? (Math.floor(displayValue * 100) / 100).toLocaleString("en-US", {
30
+ maximumFractionDigits: 2,
31
+ })
32
+ : displayValue.toLocaleString("en-US", { maximumFractionDigits: 2 });
33
+
34
+ return formatted + postfix;
35
+ }