@authdog/react-elements 0.0.49 → 0.2.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 (81) hide show
  1. package/dist/components/ui/alert.d.mts +12 -0
  2. package/dist/components/ui/alert.d.ts +12 -0
  3. package/dist/components/ui/avatar.d.mts +8 -0
  4. package/dist/components/ui/avatar.d.ts +8 -0
  5. package/dist/components/ui/badge.d.mts +12 -0
  6. package/dist/components/ui/badge.d.ts +12 -0
  7. package/dist/components/ui/button.d.mts +14 -0
  8. package/dist/components/ui/button.d.ts +14 -0
  9. package/dist/components/ui/button.js.map +1 -1
  10. package/dist/components/ui/button.mjs.map +1 -1
  11. package/dist/components/ui/card.d.mts +11 -0
  12. package/dist/components/ui/card.d.ts +11 -0
  13. package/dist/components/ui/dropdown-menu.d.mts +27 -0
  14. package/dist/components/ui/dropdown-menu.d.ts +27 -0
  15. package/dist/components/ui/input.d.mts +5 -0
  16. package/dist/components/ui/input.d.ts +5 -0
  17. package/dist/components/ui/label.d.mts +6 -0
  18. package/dist/components/ui/label.d.ts +6 -0
  19. package/dist/components/ui/separator.d.mts +6 -0
  20. package/dist/components/ui/separator.d.ts +6 -0
  21. package/dist/components/ui/sheet.d.mts +15 -0
  22. package/dist/components/ui/sheet.d.ts +15 -0
  23. package/dist/components/ui/theme-toggle.d.mts +5 -0
  24. package/dist/components/ui/theme-toggle.d.ts +5 -0
  25. package/dist/components/ui/theme-toggle.js.map +1 -1
  26. package/dist/components/ui/theme-toggle.mjs.map +1 -1
  27. package/dist/index.d.mts +12 -21
  28. package/dist/index.d.ts +12 -21
  29. package/dist/index.js +1 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +1 -1
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/lib/utils.d.mts +5 -0
  34. package/dist/lib/utils.d.ts +5 -0
  35. package/dist/styles.css +1 -4
  36. package/package.json +40 -25
  37. package/.eslintrc.js +0 -9
  38. package/.storybook/main.ts +0 -21
  39. package/.storybook/preview.ts +0 -17
  40. package/.storybook/vitest.setup.ts +0 -7
  41. package/.turbo/turbo-build.log +0 -77
  42. package/CHANGELOG.md +0 -286
  43. package/components.json +0 -20
  44. package/postcss.config.mjs +0 -11
  45. package/src/components/core/client-only.tsx +0 -15
  46. package/src/components/core/navbar.tsx +0 -307
  47. package/src/components/core/placeholder-alert.tsx +0 -23
  48. package/src/components/core/user-dropdown.tsx +0 -160
  49. package/src/components/core/user-profile.tsx +0 -521
  50. package/src/components/flow/login.tsx +0 -167
  51. package/src/components/flow/totp-validator.tsx +0 -252
  52. package/src/components/icons.tsx +0 -30
  53. package/src/components/ui/alert.tsx +0 -66
  54. package/src/components/ui/avatar.tsx +0 -53
  55. package/src/components/ui/badge.tsx +0 -46
  56. package/src/components/ui/button.tsx +0 -56
  57. package/src/components/ui/card.tsx +0 -92
  58. package/src/components/ui/dropdown-menu.tsx +0 -265
  59. package/src/components/ui/input.tsx +0 -21
  60. package/src/components/ui/label.tsx +0 -24
  61. package/src/components/ui/separator.tsx +0 -28
  62. package/src/components/ui/sheet.tsx +0 -142
  63. package/src/components/ui/theme-toggle.tsx +0 -56
  64. package/src/global.css +0 -81
  65. package/src/index.ts +0 -8
  66. package/src/lib/utils.ts +0 -6
  67. package/src/stories/core/Navbar.stories.tsx +0 -51
  68. package/src/stories/core/PlaceholderAlert.stories.tsx +0 -23
  69. package/src/stories/core/UserDropdown.stories.tsx +0 -56
  70. package/src/stories/core/UserProfile.stories.tsx +0 -47
  71. package/src/stories/flow/LoginForm.stories.tsx +0 -20
  72. package/src/stories/flow/TotpValidator.stories.tsx +0 -23
  73. package/src/stories/showcase/Landing.stories.tsx +0 -376
  74. package/src/stories/ui/Button.stories.tsx +0 -45
  75. package/src/types.ts +0 -0
  76. package/tailwind.config.ts +0 -82
  77. package/tsconfig.json +0 -11
  78. package/tsup.config.ts +0 -31
  79. package/vitest.config.ts +0 -39
  80. package/vitest.shims.d.ts +0 -1
  81. package/wrangler.prod.toml +0 -4
@@ -1,252 +0,0 @@
1
- "use client";
2
-
3
- import type React from "react";
4
-
5
- import { useState, useRef } from "react";
6
- import { Button } from "../../components/ui/button";
7
- import { Card, CardContent } from "../../components/ui/card";
8
- import { Alert, AlertDescription } from "../../components/ui/alert";
9
- import { Shield, CheckCircle, AlertCircle } from "lucide-react";
10
-
11
- interface TOTPValidatorProps {
12
- onValidate: (code: string) => Promise<void>;
13
- }
14
-
15
- export const TOTPValidator = ({ onValidate }: TOTPValidatorProps) => {
16
- const [code, setCode] = useState(["", "", "", "", "", ""]);
17
- const [loading, setLoading] = useState(false);
18
- const [error, setError] = useState("");
19
- const [success, setSuccess] = useState(false);
20
- const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
21
-
22
- const handleInputChange = (index: number, value: string) => {
23
- // Only allow digits
24
- if (!/^\d*$/.test(value)) return;
25
-
26
- const newCode = [...code];
27
- newCode[index] = value.slice(-1); // Only take the last character
28
-
29
- setCode(newCode);
30
- setError("");
31
- setSuccess(false);
32
-
33
- // Auto-focus next input
34
- if (value && index < 5) {
35
- inputRefs.current[index + 1]?.focus();
36
- }
37
- };
38
-
39
- const handleKeyDown = (index: number, e: React.KeyboardEvent) => {
40
- // Handle backspace
41
- if (e.key === "Backspace" && !code[index] && index > 0) {
42
- inputRefs.current[index - 1]?.focus();
43
- }
44
-
45
- // Handle paste
46
- if (e.key === "v" && (e.ctrlKey || e.metaKey)) {
47
- e.preventDefault();
48
- navigator.clipboard.readText().then((text) => {
49
- const digits = text.replace(/\D/g, "").slice(0, 6).split("");
50
- const newCode = [...code];
51
- digits.forEach((digit, i) => {
52
- if (i < 6) newCode[i] = digit;
53
- });
54
- setCode(newCode);
55
-
56
- // Focus the next empty input or the last one
57
- const nextIndex = Math.min(digits.length, 5);
58
- inputRefs.current[nextIndex]?.focus();
59
- });
60
- }
61
- };
62
-
63
- const validateTOTP = async () => {
64
- const totpCode = code.join("");
65
-
66
- if (totpCode.length !== 6) {
67
- setError("Please enter all 6 digits");
68
- return;
69
- }
70
-
71
- setLoading(true);
72
- setError("");
73
-
74
- try {
75
- await onValidate(totpCode);
76
- setSuccess(true);
77
- } catch (error) {
78
- setError("Invalid TOTP code. Please try again.");
79
- } finally {
80
- setLoading(false);
81
- }
82
-
83
- // try {
84
- // Call your TOTP validation endpoint
85
- // const response = await fetch("/api/validate-totp", {
86
- // method: "POST",
87
- // headers: {
88
- // "Content-Type": "application/json",
89
- // },
90
- // body: JSON.stringify({ code: totpCode }),
91
- // })
92
-
93
- // // Check if response is JSON
94
- // const contentType = response.headers.get("content-type")
95
- // if (!contentType || !contentType.includes("application/json")) {
96
- // throw new Error("Server returned non-JSON response")
97
- // }
98
-
99
- // const result = await response.json()
100
-
101
- // if (response.ok && result.valid) {
102
- // setSuccess(true)
103
- // setError("")
104
- // } else {
105
- // setError(result.message || "Invalid TOTP code. Please try again.")
106
- // // Clear the code on error
107
- // setCode(["", "", "", "", "", ""])
108
- // inputRefs.current[0]?.focus()
109
- // }
110
- // } catch (err) {
111
- // console.error("TOTP validation error:", err)
112
- // if (err instanceof Error && err.message.includes("non-JSON")) {
113
- // setError("Server error. Please try again later.")
114
- // } else {
115
- // setError("Network error. Please try again.")
116
- // }
117
- // // Clear the code on error
118
- // setCode(["", "", "", "", "", ""])
119
- // inputRefs.current[0]?.focus()
120
- // } finally {
121
- // setLoading(false)
122
- // }
123
- };
124
-
125
- const handleSubmit = (e: React.FormEvent) => {
126
- e.preventDefault();
127
- validateTOTP();
128
- };
129
-
130
- const clearCode = () => {
131
- setCode(["", "", "", "", "", ""]);
132
- setError("");
133
- setSuccess(false);
134
- setLoading(false);
135
- inputRefs.current[0]?.focus();
136
- };
137
-
138
- if (success) {
139
- return (
140
- <div className="max-w-md mx-auto">
141
- <Card className="border-green-200 bg-green-50">
142
- <CardContent className="pt-6">
143
- <div className="text-center space-y-4">
144
- <div className="mx-auto w-16 h-16 bg-green-100 rounded-full flex items-center justify-center">
145
- <CheckCircle className="w-8 h-8 text-green-600" />
146
- </div>
147
- <div>
148
- <h3 className="text-lg font-semibold text-green-900">
149
- Verification Successful!
150
- </h3>
151
- <p className="text-sm text-green-700 mt-1">
152
- Your TOTP code has been validated.
153
- </p>
154
- </div>
155
- <Button
156
- onClick={clearCode}
157
- variant="outline"
158
- className="bg-white"
159
- >
160
- Verify Another Code
161
- </Button>
162
- </div>
163
- </CardContent>
164
- </Card>
165
- </div>
166
- );
167
- }
168
-
169
- return (
170
- <div className="max-w-md mx-auto">
171
- <Card>
172
- <CardContent className="pt-6">
173
- <div className="text-center space-y-6">
174
- <div>
175
- <div className="mx-auto w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mb-4">
176
- <Shield className="w-6 h-6 text-blue-600" />
177
- </div>
178
- <h3 className="text-lg font-semibold">Enter Verification Code</h3>
179
- <p className="text-sm text-muted-foreground mt-1">
180
- Enter the 6-digit code from your authenticator app
181
- </p>
182
- </div>
183
-
184
- <form onSubmit={handleSubmit} className="space-y-6">
185
- <div className="flex justify-center gap-2">
186
- {code.map((digit, index) => (
187
- <Card
188
- key={index}
189
- className="w-12 h-14 border-2 focus-within:border-blue-500 transition-colors"
190
- >
191
- <CardContent className="p-0 h-full flex items-center justify-center">
192
- <input
193
- ref={(el) => {
194
- inputRefs.current[index] = el;
195
- }}
196
- type="tel"
197
- inputMode="numeric"
198
- maxLength={1}
199
- value={digit}
200
- onChange={(e) =>
201
- handleInputChange(index, e.target.value)
202
- }
203
- onKeyDown={(e) => handleKeyDown(index, e)}
204
- className="w-full h-full text-center text-2xl font-bold border-none outline-none bg-transparent"
205
- autoComplete="one-time-code"
206
- disabled={loading}
207
- style={{
208
- height: "auto",
209
- }}
210
- />
211
- </CardContent>
212
- </Card>
213
- ))}
214
- </div>
215
-
216
- {error && (
217
- <Alert variant="destructive">
218
- <AlertCircle className="h-4 w-4" />
219
- <AlertDescription>{error}</AlertDescription>
220
- </Alert>
221
- )}
222
-
223
- <div className="space-y-3">
224
- <Button
225
- type="submit"
226
- className="w-full"
227
- disabled={loading || code.some((digit) => digit === "")}
228
- >
229
- {loading ? "Verifying..." : "Verify Code"}
230
- </Button>
231
-
232
- <Button
233
- type="button"
234
- variant="ghost"
235
- size="sm"
236
- onClick={clearCode}
237
- className="w-full text-xs"
238
- >
239
- Clear Code
240
- </Button>
241
- </div>
242
- </form>
243
-
244
- <p className="text-xs text-muted-foreground">
245
- Codes refresh every 30 seconds
246
- </p>
247
- </div>
248
- </CardContent>
249
- </Card>
250
- </div>
251
- );
252
- };
@@ -1,30 +0,0 @@
1
- import { LucideProps } from "lucide-react";
2
- import { useEffect, useState } from "react";
3
-
4
- const iconProps: LucideProps = {
5
- className: "mr-2 h-4 w-4 text-current",
6
- "aria-hidden": "true",
7
- };
8
-
9
- export const IconWrapper = ({ Icon, withMargin = true }: { Icon: any; withMargin?: boolean }) => {
10
- const [isMounted, setIsMounted] = useState(false);
11
-
12
- useEffect(() => {
13
- setIsMounted(true);
14
- }, []);
15
-
16
- const iconClassWithMargin: LucideProps = withMargin ? iconProps : {
17
- className: "h-4 w-4 text-current",
18
- "aria-hidden": "true",
19
- };
20
-
21
- return (
22
- <span className="inline-flex items-center justify-center">
23
- {!isMounted ? (
24
- <span className={withMargin ? "mr-2 h-4 w-4" : "h-4 w-4"} aria-hidden="true" />
25
- ) : (
26
- <Icon {...iconClassWithMargin} />
27
- )}
28
- </span>
29
- );
30
- };
@@ -1,66 +0,0 @@
1
- import * as React from "react";
2
- import { cva, type VariantProps } from "class-variance-authority";
3
-
4
- import { cn } from "../../lib/utils";
5
-
6
- const alertVariants = cva(
7
- "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
8
- {
9
- variants: {
10
- variant: {
11
- default: "bg-card text-card-foreground",
12
- destructive:
13
- "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
14
- },
15
- },
16
- defaultVariants: {
17
- variant: "default",
18
- },
19
- },
20
- );
21
-
22
- function Alert({
23
- className,
24
- variant,
25
- ...props
26
- }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
27
- return (
28
- <div
29
- data-slot="alert"
30
- role="alert"
31
- className={cn(alertVariants({ variant }), className)}
32
- {...props}
33
- />
34
- );
35
- }
36
-
37
- function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
38
- return (
39
- <div
40
- data-slot="alert-title"
41
- className={cn(
42
- "col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight",
43
- className,
44
- )}
45
- {...props}
46
- />
47
- );
48
- }
49
-
50
- function AlertDescription({
51
- className,
52
- ...props
53
- }: React.ComponentProps<"div">) {
54
- return (
55
- <div
56
- data-slot="alert-description"
57
- className={cn(
58
- "text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
59
- className,
60
- )}
61
- {...props}
62
- />
63
- );
64
- }
65
-
66
- export { Alert, AlertTitle, AlertDescription };
@@ -1,53 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
- import * as AvatarPrimitive from "@radix-ui/react-avatar";
5
-
6
- import { cn } from "../../lib/utils";
7
-
8
- function Avatar({
9
- className,
10
- ...props
11
- }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
12
- return (
13
- <AvatarPrimitive.Root
14
- data-slot="avatar"
15
- className={cn(
16
- "relative flex size-8 shrink-0 overflow-hidden rounded-full",
17
- className,
18
- )}
19
- {...props}
20
- />
21
- );
22
- }
23
-
24
- function AvatarImage({
25
- className,
26
- ...props
27
- }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
28
- return (
29
- <AvatarPrimitive.Image
30
- data-slot="avatar-image"
31
- className={cn("aspect-square size-full", className)}
32
- {...props}
33
- />
34
- );
35
- }
36
-
37
- function AvatarFallback({
38
- className,
39
- ...props
40
- }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
41
- return (
42
- <AvatarPrimitive.Fallback
43
- data-slot="avatar-fallback"
44
- className={cn(
45
- "bg-muted flex size-full items-center justify-center rounded-full",
46
- className,
47
- )}
48
- {...props}
49
- />
50
- );
51
- }
52
-
53
- export { Avatar, AvatarImage, AvatarFallback };
@@ -1,46 +0,0 @@
1
- import * as React from "react";
2
- import { Slot } from "@radix-ui/react-slot";
3
- import { cva, type VariantProps } from "class-variance-authority";
4
-
5
- import { cn } from "../../lib/utils";
6
-
7
- const badgeVariants = cva(
8
- "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
9
- {
10
- variants: {
11
- variant: {
12
- default:
13
- "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
14
- secondary:
15
- "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
16
- destructive:
17
- "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
18
- outline:
19
- "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
20
- },
21
- },
22
- defaultVariants: {
23
- variant: "default",
24
- },
25
- },
26
- );
27
-
28
- function Badge({
29
- className,
30
- variant,
31
- asChild = false,
32
- ...props
33
- }: React.ComponentProps<"span"> &
34
- VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
35
- const Comp = asChild ? Slot : "span";
36
-
37
- return (
38
- <Comp
39
- data-slot="badge"
40
- className={cn(badgeVariants({ variant }), className)}
41
- {...props}
42
- />
43
- );
44
- }
45
-
46
- export { Badge, badgeVariants };
@@ -1,56 +0,0 @@
1
- import * as React from "react";
2
- import { Slot } from "@radix-ui/react-slot";
3
- import { cva, type VariantProps } from "class-variance-authority";
4
-
5
- import { cn } from "../../lib/utils";
6
-
7
- const buttonVariants = cva(
8
- "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
9
- {
10
- variants: {
11
- variant: {
12
- default: "bg-primary text-primary-foreground hover:bg-primary/90",
13
- destructive:
14
- "bg-destructive text-destructive-foreground hover:bg-destructive/90",
15
- outline:
16
- "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
17
- secondary:
18
- "bg-secondary text-secondary-foreground hover:bg-secondary/80",
19
- ghost: "hover:bg-accent hover:text-accent-foreground",
20
- link: "text-primary underline-offset-4 hover:underline",
21
- },
22
- size: {
23
- default: "h-10 px-4 py-2",
24
- sm: "h-9 rounded-md px-3",
25
- lg: "h-11 rounded-md px-8",
26
- icon: "h-10 w-10",
27
- },
28
- },
29
- defaultVariants: {
30
- variant: "default",
31
- size: "default",
32
- },
33
- },
34
- );
35
-
36
- export interface ButtonProps
37
- extends React.ButtonHTMLAttributes<HTMLButtonElement>,
38
- VariantProps<typeof buttonVariants> {
39
- asChild?: boolean;
40
- }
41
-
42
- const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
43
- ({ className, variant, size, asChild = false, ...props }, ref) => {
44
- const Comp = asChild ? Slot : "button";
45
- return (
46
- <Comp
47
- className={cn(buttonVariants({ variant, size, className }))}
48
- ref={ref}
49
- {...props}
50
- />
51
- );
52
- },
53
- );
54
- Button.displayName = "Button";
55
-
56
- export { Button, buttonVariants };
@@ -1,92 +0,0 @@
1
- import * as React from "react";
2
-
3
- import { cn } from "../../lib/utils";
4
-
5
- function Card({ className, ...props }: React.ComponentProps<"div">) {
6
- return (
7
- <div
8
- data-slot="card"
9
- className={cn(
10
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
11
- className,
12
- )}
13
- {...props}
14
- />
15
- );
16
- }
17
-
18
- function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
19
- return (
20
- <div
21
- data-slot="card-header"
22
- className={cn(
23
- "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
24
- className,
25
- )}
26
- {...props}
27
- />
28
- );
29
- }
30
-
31
- function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
32
- return (
33
- <div
34
- data-slot="card-title"
35
- className={cn("leading-none font-semibold", className)}
36
- {...props}
37
- />
38
- );
39
- }
40
-
41
- function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
42
- return (
43
- <div
44
- data-slot="card-description"
45
- className={cn("text-muted-foreground text-sm", className)}
46
- {...props}
47
- />
48
- );
49
- }
50
-
51
- function CardAction({ className, ...props }: React.ComponentProps<"div">) {
52
- return (
53
- <div
54
- data-slot="card-action"
55
- className={cn(
56
- "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
57
- className,
58
- )}
59
- {...props}
60
- />
61
- );
62
- }
63
-
64
- function CardContent({ className, ...props }: React.ComponentProps<"div">) {
65
- return (
66
- <div
67
- data-slot="card-content"
68
- className={cn("px-6", className)}
69
- {...props}
70
- />
71
- );
72
- }
73
-
74
- function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
75
- return (
76
- <div
77
- data-slot="card-footer"
78
- className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
79
- {...props}
80
- />
81
- );
82
- }
83
-
84
- export {
85
- Card,
86
- CardHeader,
87
- CardFooter,
88
- CardTitle,
89
- CardAction,
90
- CardDescription,
91
- CardContent,
92
- };