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,282 @@
1
+ import React from "react";
2
+
3
+ export type EphemeralVariant = "info" | "success";
4
+ export type StatusVariant = "info" | "success" | "error";
5
+
6
+ export interface ToastAction {
7
+ label: string;
8
+ icon?: React.ReactNode;
9
+ onClick: () => void;
10
+ highlight?: boolean;
11
+ }
12
+
13
+ /* ── Self-contained SVG icons ─────────────────────────── */
14
+
15
+ function InfoIcon({ className }: { className?: string }) {
16
+ return (
17
+ <svg
18
+ className={className}
19
+ width="20"
20
+ height="20"
21
+ viewBox="0 0 20 20"
22
+ fill="none"
23
+ xmlns="http://www.w3.org/2000/svg"
24
+ >
25
+ <path
26
+ fillRule="evenodd"
27
+ clipRule="evenodd"
28
+ d="M10 1.667A8.333 8.333 0 1 0 10 18.333 8.333 8.333 0 0 0 10 1.667ZM10.833 6.667a.833.833 0 1 1-1.666 0 .833.833 0 0 1 1.666 0ZM10 8.75a.625.625 0 0 1 .625.625v4.375a.625.625 0 1 1-1.25 0V9.375A.625.625 0 0 1 10 8.75Z"
29
+ fill="var(--toast-icon-info, #3FC1FF)"
30
+ />
31
+ </svg>
32
+ );
33
+ }
34
+
35
+ function CheckIcon({ className }: { className?: string }) {
36
+ return (
37
+ <svg
38
+ className={className}
39
+ width="20"
40
+ height="20"
41
+ viewBox="0 0 20 20"
42
+ fill="none"
43
+ xmlns="http://www.w3.org/2000/svg"
44
+ >
45
+ <path
46
+ d="M16.707 5.293a1 1 0 0 1 0 1.414l-8 8a1 1 0 0 1-1.414 0l-4-4a1 1 0 1 1 1.414-1.414L8 12.586l7.293-7.293a1 1 0 0 1 1.414 0Z"
47
+ fill="var(--toast-icon-success, #00A95D)"
48
+ />
49
+ </svg>
50
+ );
51
+ }
52
+
53
+ function SuccessCircleIcon({ className }: { className?: string }) {
54
+ return (
55
+ <svg
56
+ className={className}
57
+ width="20"
58
+ height="20"
59
+ viewBox="0 0 20 20"
60
+ fill="none"
61
+ xmlns="http://www.w3.org/2000/svg"
62
+ >
63
+ <path
64
+ fillRule="evenodd"
65
+ clipRule="evenodd"
66
+ d="M10 1.667A8.333 8.333 0 1 0 10 18.333 8.333 8.333 0 0 0 10 1.667Zm3.577 6.077a.625.625 0 1 0-.904-.863L8.75 11.21 7.328 9.674a.625.625 0 1 0-.905.862l1.875 1.968a.625.625 0 0 0 .905 0l4.374-4.76Z"
67
+ fill="var(--toast-icon-success, #00A95D)"
68
+ />
69
+ </svg>
70
+ );
71
+ }
72
+
73
+ function ErrorCircleIcon({ className }: { className?: string }) {
74
+ return (
75
+ <svg
76
+ className={className}
77
+ width="20"
78
+ height="20"
79
+ viewBox="0 0 20 20"
80
+ fill="none"
81
+ xmlns="http://www.w3.org/2000/svg"
82
+ >
83
+ <path
84
+ fillRule="evenodd"
85
+ clipRule="evenodd"
86
+ d="M10 1.667A8.333 8.333 0 1 0 10 18.333 8.333 8.333 0 0 0 10 1.667ZM10.833 6.667a.833.833 0 1 1-1.666 0 .833.833 0 0 1 1.666 0ZM10 8.75a.625.625 0 0 1 .625.625v4.375a.625.625 0 1 1-1.25 0V9.375A.625.625 0 0 1 10 8.75Z"
87
+ fill="var(--toast-icon-error, #AF1B45)"
88
+ />
89
+ </svg>
90
+ );
91
+ }
92
+
93
+ function WarningIcon({ className }: { className?: string }) {
94
+ return (
95
+ <svg
96
+ className={className}
97
+ width="20"
98
+ height="20"
99
+ viewBox="0 0 20 20"
100
+ fill="none"
101
+ xmlns="http://www.w3.org/2000/svg"
102
+ >
103
+ <path
104
+ fillRule="evenodd"
105
+ clipRule="evenodd"
106
+ d="M10 1.667A8.333 8.333 0 1 0 10 18.333 8.333 8.333 0 0 0 10 1.667ZM10.833 6.667a.833.833 0 1 1-1.666 0 .833.833 0 0 1 1.666 0ZM10 8.75a.625.625 0 0 1 .625.625v4.375a.625.625 0 1 1-1.25 0V9.375A.625.625 0 0 1 10 8.75Z"
107
+ fill="var(--toast-icon-warning, #AF1B45)"
108
+ />
109
+ </svg>
110
+ );
111
+ }
112
+
113
+ function CloseIcon({ className }: { className?: string }) {
114
+ return (
115
+ <svg
116
+ className={className}
117
+ width="16"
118
+ height="16"
119
+ viewBox="0 0 16 16"
120
+ fill="none"
121
+ xmlns="http://www.w3.org/2000/svg"
122
+ >
123
+ <path
124
+ d="M12.207 4.707a1 1 0 0 0-1.414-1.414L8 6.086 5.207 3.293a1 1 0 0 0-1.414 1.414L6.586 7.5l-2.793 2.793a1 1 0 1 0 1.414 1.414L8 8.914l2.793 2.793a1 1 0 0 0 1.414-1.414L9.414 7.5l2.793-2.793Z"
125
+ fill="var(--toast-text-secondary, #BFBFBF)"
126
+ />
127
+ </svg>
128
+ );
129
+ }
130
+
131
+ /* ── Icon resolver per toast kind + variant ────────────── */
132
+
133
+ const EPHEMERAL_ICON: Record<
134
+ EphemeralVariant,
135
+ React.FC<{ className?: string }>
136
+ > = {
137
+ info: InfoIcon,
138
+ success: CheckIcon,
139
+ };
140
+
141
+ const STATUS_ICON: Record<StatusVariant, React.FC<{ className?: string }>> = {
142
+ info: InfoIcon,
143
+ success: SuccessCircleIcon,
144
+ error: ErrorCircleIcon,
145
+ };
146
+
147
+ /* ── Ephemeral Toast ──────────────────────────────────── */
148
+
149
+ export function EphemeralToast({
150
+ message,
151
+ variant = "info",
152
+ }: {
153
+ message: string;
154
+ variant: EphemeralVariant;
155
+ }) {
156
+ const Icon = EPHEMERAL_ICON[variant];
157
+
158
+ return (
159
+ <div className="casino-toast-ephemeral flex gap-3 items-start rounded-xl border border-(--toast-border,rgba(255,255,255,0.04)) bg-(--toast-bg,#1F1F1F) p-3 shadow-(--toast-shadow,0px_6px_15px_-3px_rgba(0,0,0,0.15)) w-[330px]">
160
+ <Icon className="shrink-0" />
161
+ <p className="text-sm font-normal text-(--toast-text-primary,#FFFFFF) leading-5 overflow-hidden text-ellipsis">
162
+ {message}
163
+ </p>
164
+ </div>
165
+ );
166
+ }
167
+
168
+ /* ── Status Toast ─────────────────────────────────────── */
169
+
170
+ export function StatusToast({
171
+ message,
172
+ title,
173
+ variant = "info",
174
+ onClose,
175
+ }: {
176
+ message: string;
177
+ title?: string;
178
+ variant: StatusVariant;
179
+ onClose?: () => void;
180
+ }) {
181
+ const Icon = STATUS_ICON[variant];
182
+
183
+ return (
184
+ <div className="casino-toast-status flex gap-2 rounded-xl border border-(--toast-border,rgba(255,255,255,0.04)) bg-(--toast-bg,#1F1F1F) p-3 shadow-(--toast-shadow,0px_6px_15px_-3px_rgba(0,0,0,0.15)) w-[354px] items-start">
185
+ <div className={`flex gap-3 flex-1 min-w-0`}>
186
+ <Icon className="shrink-0" />
187
+ <div className="flex flex-col min-w-0">
188
+ {title && (
189
+ <p className="text-base font-semibold text-(--toast-text-primary,#FFFFFF) leading-[19.2px] tracking-[-0.32px] overflow-hidden text-ellipsis">
190
+ {title}
191
+ </p>
192
+ )}
193
+ <p className="text-sm font-normal text-(--toast-text-secondary,#BFBFBF) leading-5 overflow-hidden text-ellipsis">
194
+ {message}
195
+ </p>
196
+ </div>
197
+ </div>
198
+ {onClose && (
199
+ <button
200
+ type="button"
201
+ onClick={onClose}
202
+ className="shrink-0 cursor-pointer opacity-60 hover:opacity-100 transition-opacity"
203
+ aria-label="Close"
204
+ >
205
+ <CloseIcon />
206
+ </button>
207
+ )}
208
+ </div>
209
+ );
210
+ }
211
+
212
+ /* ── Action Toast ─────────────────────────────────────── */
213
+
214
+ export function ActionToast({
215
+ message,
216
+ title,
217
+ actions,
218
+ onClose,
219
+ }: {
220
+ message: string;
221
+ title?: string;
222
+ actions: ToastAction[];
223
+ onClose?: () => void;
224
+ }) {
225
+ return (
226
+ <div className="casino-toast-action flex gap-2 items-start rounded-xl border border-(--toast-border,rgba(255,255,255,0.04)) bg-(--toast-bg,#1F1F1F) p-3 shadow-(--toast-shadow,0px_6px_15px_-3px_rgba(0,0,0,0.15)) w-[354px]">
227
+ <div className="flex gap-3 items-start flex-1 min-w-0">
228
+ <WarningIcon className="shrink-0 mt-px" />
229
+ <div className="flex flex-col gap-2 min-w-0">
230
+ <div className="flex flex-col">
231
+ {title && (
232
+ <p className="text-base font-semibold text-(--toast-text-primary,#FFFFFF) leading-[19.2px] tracking-[-0.32px] overflow-hidden text-ellipsis">
233
+ {title}
234
+ </p>
235
+ )}
236
+ <p className="text-sm font-normal text-(--toast-text-secondary,#BFBFBF) leading-5 overflow-hidden text-ellipsis">
237
+ {message}
238
+ </p>
239
+ </div>
240
+ {actions.length > 0 && (
241
+ <div className="flex gap-4 items-center">
242
+ {actions.map((action) => (
243
+ <button
244
+ key={action.label}
245
+ type="button"
246
+ onClick={action.onClick}
247
+ className="flex items-center gap-1 cursor-pointer"
248
+ >
249
+ {action.icon && (
250
+ <span className="shrink-0 w-4 h-4 flex items-center justify-center">
251
+ {action.icon}
252
+ </span>
253
+ )}
254
+ <span
255
+ className="text-sm font-semibold leading-[16.8px] whitespace-nowrap"
256
+ style={{
257
+ color: action.highlight
258
+ ? "var(--toast-action-highlight, #9FCC41)"
259
+ : "var(--toast-text-secondary, #BFBFBF)",
260
+ }}
261
+ >
262
+ {action.label}
263
+ </span>
264
+ </button>
265
+ ))}
266
+ </div>
267
+ )}
268
+ </div>
269
+ </div>
270
+ {onClose && (
271
+ <button
272
+ type="button"
273
+ onClick={onClose}
274
+ className="shrink-0 cursor-pointer opacity-60 hover:opacity-100 transition-opacity"
275
+ aria-label="Close"
276
+ >
277
+ <CloseIcon />
278
+ </button>
279
+ )}
280
+ </div>
281
+ );
282
+ }
@@ -0,0 +1,134 @@
1
+ import * as React from "react";
2
+ import { Dialog as DialogPrimitive } from "radix-ui";
3
+
4
+ import { cn } from "../../lib/utils";
5
+
6
+ function Dialog({
7
+ ...props
8
+ }: React.ComponentProps<typeof DialogPrimitive.Root>) {
9
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />;
10
+ }
11
+
12
+ function DialogTrigger({
13
+ ...props
14
+ }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
15
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
16
+ }
17
+
18
+ function DialogPortal({
19
+ ...props
20
+ }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
21
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
22
+ }
23
+
24
+ function DialogClose({
25
+ ...props
26
+ }: React.ComponentProps<typeof DialogPrimitive.Close>) {
27
+ return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
28
+ }
29
+
30
+ function DialogOverlay({
31
+ className,
32
+ ...props
33
+ }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
34
+ return (
35
+ <DialogPrimitive.Overlay
36
+ data-slot="dialog-overlay"
37
+ className={cn(
38
+ "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
39
+ className,
40
+ )}
41
+ {...props}
42
+ />
43
+ );
44
+ }
45
+
46
+ function DialogContent({
47
+ className,
48
+ children,
49
+ ...props
50
+ }: React.ComponentProps<typeof DialogPrimitive.Content>) {
51
+ return (
52
+ <DialogPortal data-slot="dialog-portal">
53
+ <DialogOverlay />
54
+ <DialogPrimitive.Content
55
+ data-slot="dialog-content"
56
+ className={cn(
57
+ "fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] bg-background shadow-lg duration-200 outline-none data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg",
58
+ className,
59
+ )}
60
+ {...props}
61
+ >
62
+ {children}
63
+ </DialogPrimitive.Content>
64
+ </DialogPortal>
65
+ );
66
+ }
67
+
68
+ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
69
+ return (
70
+ <div
71
+ data-slot="dialog-header"
72
+ className={cn("flex gap-2 text-center sm:text-left", className)}
73
+ {...props}
74
+ />
75
+ );
76
+ }
77
+
78
+ function DialogFooter({
79
+ className,
80
+ children,
81
+ ...props
82
+ }: React.ComponentProps<"div">) {
83
+ return (
84
+ <div
85
+ data-slot="dialog-footer"
86
+ className={cn(
87
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
88
+ className,
89
+ )}
90
+ {...props}
91
+ >
92
+ {children}
93
+ </div>
94
+ );
95
+ }
96
+
97
+ function DialogTitle({
98
+ className,
99
+ ...props
100
+ }: React.ComponentProps<typeof DialogPrimitive.Title>) {
101
+ return (
102
+ <DialogPrimitive.Title
103
+ data-slot="dialog-title"
104
+ className={cn("text-lg leading-none font-semibold", className)}
105
+ {...props}
106
+ />
107
+ );
108
+ }
109
+
110
+ function DialogDescription({
111
+ className,
112
+ ...props
113
+ }: React.ComponentProps<typeof DialogPrimitive.Description>) {
114
+ return (
115
+ <DialogPrimitive.Description
116
+ data-slot="dialog-description"
117
+ className={cn("text-sm text-muted-foreground", className)}
118
+ {...props}
119
+ />
120
+ );
121
+ }
122
+
123
+ export {
124
+ Dialog,
125
+ DialogClose,
126
+ DialogContent,
127
+ DialogDescription,
128
+ DialogFooter,
129
+ DialogHeader,
130
+ DialogOverlay,
131
+ DialogPortal,
132
+ DialogTitle,
133
+ DialogTrigger,
134
+ };
@@ -0,0 +1,132 @@
1
+ import * as React from "react";
2
+ import { Drawer as DrawerPrimitive } from "vaul";
3
+
4
+ import { cn } from "../../lib/utils";
5
+
6
+ function Drawer({
7
+ ...props
8
+ }: React.ComponentProps<typeof DrawerPrimitive.Root>) {
9
+ return <DrawerPrimitive.Root data-slot="drawer" {...props} />;
10
+ }
11
+
12
+ function DrawerTrigger({
13
+ ...props
14
+ }: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
15
+ return <DrawerPrimitive.Trigger data-slot="drawer-trigger" {...props} />;
16
+ }
17
+
18
+ function DrawerPortal({
19
+ ...props
20
+ }: React.ComponentProps<typeof DrawerPrimitive.Portal>) {
21
+ return <DrawerPrimitive.Portal data-slot="drawer-portal" {...props} />;
22
+ }
23
+
24
+ function DrawerClose({
25
+ ...props
26
+ }: React.ComponentProps<typeof DrawerPrimitive.Close>) {
27
+ return <DrawerPrimitive.Close data-slot="drawer-close" {...props} />;
28
+ }
29
+
30
+ function DrawerOverlay({
31
+ className,
32
+ ...props
33
+ }: React.ComponentProps<typeof DrawerPrimitive.Overlay>) {
34
+ return (
35
+ <DrawerPrimitive.Overlay
36
+ data-slot="drawer-overlay"
37
+ className={cn(
38
+ "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
39
+ className,
40
+ )}
41
+ {...props}
42
+ />
43
+ );
44
+ }
45
+
46
+ function DrawerContent({
47
+ className,
48
+ children,
49
+ ...props
50
+ }: React.ComponentProps<typeof DrawerPrimitive.Content>) {
51
+ return (
52
+ <DrawerPortal data-slot="drawer-portal">
53
+ <DrawerOverlay />
54
+ <DrawerPrimitive.Content
55
+ data-slot="drawer-content"
56
+ className={cn(
57
+ "group/drawer-content fixed z-50 flex h-auto flex-col bg-background",
58
+ "data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
59
+ "data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-xl data-[vaul-drawer-direction=bottom]:border-t",
60
+ "data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm",
61
+ "data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm",
62
+ className,
63
+ )}
64
+ {...props}
65
+ >
66
+ {children}
67
+ </DrawerPrimitive.Content>
68
+ </DrawerPortal>
69
+ );
70
+ }
71
+
72
+ function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
73
+ return (
74
+ <div
75
+ data-slot="drawer-header"
76
+ className={cn(
77
+ "flex gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left",
78
+ className,
79
+ )}
80
+ {...props}
81
+ />
82
+ );
83
+ }
84
+
85
+ function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
86
+ return (
87
+ <div
88
+ data-slot="drawer-footer"
89
+ className={cn("mt-auto flex flex-col gap-2 p-4", className)}
90
+ {...props}
91
+ />
92
+ );
93
+ }
94
+
95
+ function DrawerTitle({
96
+ className,
97
+ ...props
98
+ }: React.ComponentProps<typeof DrawerPrimitive.Title>) {
99
+ return (
100
+ <DrawerPrimitive.Title
101
+ data-slot="drawer-title"
102
+ className={cn("font-semibold text-foreground", className)}
103
+ {...props}
104
+ />
105
+ );
106
+ }
107
+
108
+ function DrawerDescription({
109
+ className,
110
+ ...props
111
+ }: React.ComponentProps<typeof DrawerPrimitive.Description>) {
112
+ return (
113
+ <DrawerPrimitive.Description
114
+ data-slot="drawer-description"
115
+ className={cn("text-sm text-muted-foreground", className)}
116
+ {...props}
117
+ />
118
+ );
119
+ }
120
+
121
+ export {
122
+ Drawer,
123
+ DrawerPortal,
124
+ DrawerOverlay,
125
+ DrawerTrigger,
126
+ DrawerClose,
127
+ DrawerContent,
128
+ DrawerHeader,
129
+ DrawerFooter,
130
+ DrawerTitle,
131
+ DrawerDescription,
132
+ };