@victusvinceere/saas-core 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.
- package/dist/auth/index.d.mts +40 -0
- package/dist/auth/index.d.ts +40 -0
- package/dist/auth/index.js +147 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +111 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/authorization/index.d.mts +78 -0
- package/dist/authorization/index.d.ts +78 -0
- package/dist/authorization/index.js +137 -0
- package/dist/authorization/index.js.map +1 -0
- package/dist/authorization/index.mjs +104 -0
- package/dist/authorization/index.mjs.map +1 -0
- package/dist/components/auth/index.d.mts +26 -0
- package/dist/components/auth/index.d.ts +26 -0
- package/dist/components/auth/index.js +733 -0
- package/dist/components/auth/index.js.map +1 -0
- package/dist/components/auth/index.mjs +696 -0
- package/dist/components/auth/index.mjs.map +1 -0
- package/dist/components/dashboard/index.d.mts +32 -0
- package/dist/components/dashboard/index.d.ts +32 -0
- package/dist/components/dashboard/index.js +440 -0
- package/dist/components/dashboard/index.js.map +1 -0
- package/dist/components/dashboard/index.mjs +401 -0
- package/dist/components/dashboard/index.mjs.map +1 -0
- package/dist/components/ui/index.d.mts +351 -0
- package/dist/components/ui/index.d.ts +351 -0
- package/dist/components/ui/index.js +14342 -0
- package/dist/components/ui/index.js.map +1 -0
- package/dist/components/ui/index.mjs +14173 -0
- package/dist/components/ui/index.mjs.map +1 -0
- package/dist/config/index.d.mts +45 -0
- package/dist/config/index.d.ts +45 -0
- package/dist/config/index.js +71 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.mjs +44 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/hooks/index.d.mts +20 -0
- package/dist/hooks/index.d.ts +20 -0
- package/dist/hooks/index.js +103 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/index.mjs +65 -0
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/index.d.mts +21 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +459 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +401 -0
- package/dist/index.mjs.map +1 -0
- package/dist/prisma/index.d.mts +11 -0
- package/dist/prisma/index.d.ts +11 -0
- package/dist/prisma/index.js +46 -0
- package/dist/prisma/index.js.map +1 -0
- package/dist/prisma/index.mjs +20 -0
- package/dist/prisma/index.mjs.map +1 -0
- package/dist/providers/index.d.mts +37 -0
- package/dist/providers/index.d.ts +37 -0
- package/dist/providers/index.js +97 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/index.mjs +69 -0
- package/dist/providers/index.mjs.map +1 -0
- package/dist/sidebar-ttX_iZ40.d.mts +22 -0
- package/dist/sidebar-ttX_iZ40.d.ts +22 -0
- package/package.json +122 -0
- package/prisma/schema.prisma +106 -0
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/components/ui/avatar.tsx
|
|
4
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
5
|
+
|
|
6
|
+
// src/lib/utils.ts
|
|
7
|
+
import { clsx } from "clsx";
|
|
8
|
+
import { twMerge } from "tailwind-merge";
|
|
9
|
+
function cn(...inputs) {
|
|
10
|
+
return twMerge(clsx(inputs));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/components/ui/avatar.tsx
|
|
14
|
+
import { jsx } from "react/jsx-runtime";
|
|
15
|
+
function Avatar({
|
|
16
|
+
className,
|
|
17
|
+
...props
|
|
18
|
+
}) {
|
|
19
|
+
return /* @__PURE__ */ jsx(
|
|
20
|
+
AvatarPrimitive.Root,
|
|
21
|
+
{
|
|
22
|
+
"data-slot": "avatar",
|
|
23
|
+
className: cn(
|
|
24
|
+
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
|
|
25
|
+
className
|
|
26
|
+
),
|
|
27
|
+
...props
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
function AvatarImage({
|
|
32
|
+
className,
|
|
33
|
+
...props
|
|
34
|
+
}) {
|
|
35
|
+
return /* @__PURE__ */ jsx(
|
|
36
|
+
AvatarPrimitive.Image,
|
|
37
|
+
{
|
|
38
|
+
"data-slot": "avatar-image",
|
|
39
|
+
className: cn("aspect-square size-full", className),
|
|
40
|
+
...props
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
function AvatarFallback({
|
|
45
|
+
className,
|
|
46
|
+
...props
|
|
47
|
+
}) {
|
|
48
|
+
return /* @__PURE__ */ jsx(
|
|
49
|
+
AvatarPrimitive.Fallback,
|
|
50
|
+
{
|
|
51
|
+
"data-slot": "avatar-fallback",
|
|
52
|
+
className: cn(
|
|
53
|
+
"bg-muted flex size-full items-center justify-center rounded-full",
|
|
54
|
+
className
|
|
55
|
+
),
|
|
56
|
+
...props
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/components/ui/button.tsx
|
|
62
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
63
|
+
import { cva } from "class-variance-authority";
|
|
64
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
65
|
+
var buttonVariants = cva(
|
|
66
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-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",
|
|
67
|
+
{
|
|
68
|
+
variants: {
|
|
69
|
+
variant: {
|
|
70
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
71
|
+
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
72
|
+
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
73
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
74
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
75
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
76
|
+
},
|
|
77
|
+
size: {
|
|
78
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
79
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
80
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
81
|
+
icon: "size-9",
|
|
82
|
+
"icon-sm": "size-8",
|
|
83
|
+
"icon-lg": "size-10"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
defaultVariants: {
|
|
87
|
+
variant: "default",
|
|
88
|
+
size: "default"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
function Button({
|
|
93
|
+
className,
|
|
94
|
+
variant = "default",
|
|
95
|
+
size = "default",
|
|
96
|
+
asChild = false,
|
|
97
|
+
...props
|
|
98
|
+
}) {
|
|
99
|
+
const Comp = asChild ? Slot : "button";
|
|
100
|
+
return /* @__PURE__ */ jsx2(
|
|
101
|
+
Comp,
|
|
102
|
+
{
|
|
103
|
+
"data-slot": "button",
|
|
104
|
+
"data-variant": variant,
|
|
105
|
+
"data-size": size,
|
|
106
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
107
|
+
...props
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/components/ui/dropdown-menu.tsx
|
|
113
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
114
|
+
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
|
115
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
116
|
+
function DropdownMenu({
|
|
117
|
+
...props
|
|
118
|
+
}) {
|
|
119
|
+
return /* @__PURE__ */ jsx3(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
120
|
+
}
|
|
121
|
+
function DropdownMenuTrigger({
|
|
122
|
+
...props
|
|
123
|
+
}) {
|
|
124
|
+
return /* @__PURE__ */ jsx3(
|
|
125
|
+
DropdownMenuPrimitive.Trigger,
|
|
126
|
+
{
|
|
127
|
+
"data-slot": "dropdown-menu-trigger",
|
|
128
|
+
...props
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
function DropdownMenuContent({
|
|
133
|
+
className,
|
|
134
|
+
sideOffset = 4,
|
|
135
|
+
...props
|
|
136
|
+
}) {
|
|
137
|
+
return /* @__PURE__ */ jsx3(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx3(
|
|
138
|
+
DropdownMenuPrimitive.Content,
|
|
139
|
+
{
|
|
140
|
+
"data-slot": "dropdown-menu-content",
|
|
141
|
+
sideOffset,
|
|
142
|
+
className: cn(
|
|
143
|
+
"bg-popover text-popover-foreground 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 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
|
|
144
|
+
className
|
|
145
|
+
),
|
|
146
|
+
...props
|
|
147
|
+
}
|
|
148
|
+
) });
|
|
149
|
+
}
|
|
150
|
+
function DropdownMenuItem({
|
|
151
|
+
className,
|
|
152
|
+
inset,
|
|
153
|
+
variant = "default",
|
|
154
|
+
...props
|
|
155
|
+
}) {
|
|
156
|
+
return /* @__PURE__ */ jsx3(
|
|
157
|
+
DropdownMenuPrimitive.Item,
|
|
158
|
+
{
|
|
159
|
+
"data-slot": "dropdown-menu-item",
|
|
160
|
+
"data-inset": inset,
|
|
161
|
+
"data-variant": variant,
|
|
162
|
+
className: cn(
|
|
163
|
+
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
164
|
+
className
|
|
165
|
+
),
|
|
166
|
+
...props
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
function DropdownMenuLabel({
|
|
171
|
+
className,
|
|
172
|
+
inset,
|
|
173
|
+
...props
|
|
174
|
+
}) {
|
|
175
|
+
return /* @__PURE__ */ jsx3(
|
|
176
|
+
DropdownMenuPrimitive.Label,
|
|
177
|
+
{
|
|
178
|
+
"data-slot": "dropdown-menu-label",
|
|
179
|
+
"data-inset": inset,
|
|
180
|
+
className: cn(
|
|
181
|
+
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
|
182
|
+
className
|
|
183
|
+
),
|
|
184
|
+
...props
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
function DropdownMenuSeparator({
|
|
189
|
+
className,
|
|
190
|
+
...props
|
|
191
|
+
}) {
|
|
192
|
+
return /* @__PURE__ */ jsx3(
|
|
193
|
+
DropdownMenuPrimitive.Separator,
|
|
194
|
+
{
|
|
195
|
+
"data-slot": "dropdown-menu-separator",
|
|
196
|
+
className: cn("bg-border -mx-1 my-1 h-px", className),
|
|
197
|
+
...props
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/components/ui/drawer.tsx
|
|
203
|
+
import { Drawer as DrawerPrimitive } from "vaul";
|
|
204
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
205
|
+
function Drawer({
|
|
206
|
+
...props
|
|
207
|
+
}) {
|
|
208
|
+
return /* @__PURE__ */ jsx4(DrawerPrimitive.Root, { "data-slot": "drawer", ...props });
|
|
209
|
+
}
|
|
210
|
+
function DrawerTrigger({
|
|
211
|
+
...props
|
|
212
|
+
}) {
|
|
213
|
+
return /* @__PURE__ */ jsx4(DrawerPrimitive.Trigger, { "data-slot": "drawer-trigger", ...props });
|
|
214
|
+
}
|
|
215
|
+
function DrawerPortal({
|
|
216
|
+
...props
|
|
217
|
+
}) {
|
|
218
|
+
return /* @__PURE__ */ jsx4(DrawerPrimitive.Portal, { "data-slot": "drawer-portal", ...props });
|
|
219
|
+
}
|
|
220
|
+
function DrawerOverlay({
|
|
221
|
+
className,
|
|
222
|
+
...props
|
|
223
|
+
}) {
|
|
224
|
+
return /* @__PURE__ */ jsx4(
|
|
225
|
+
DrawerPrimitive.Overlay,
|
|
226
|
+
{
|
|
227
|
+
"data-slot": "drawer-overlay",
|
|
228
|
+
className: cn(
|
|
229
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
|
230
|
+
className
|
|
231
|
+
),
|
|
232
|
+
...props
|
|
233
|
+
}
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
function DrawerContent({
|
|
237
|
+
className,
|
|
238
|
+
children,
|
|
239
|
+
...props
|
|
240
|
+
}) {
|
|
241
|
+
return /* @__PURE__ */ jsxs2(DrawerPortal, { "data-slot": "drawer-portal", children: [
|
|
242
|
+
/* @__PURE__ */ jsx4(DrawerOverlay, {}),
|
|
243
|
+
/* @__PURE__ */ jsxs2(
|
|
244
|
+
DrawerPrimitive.Content,
|
|
245
|
+
{
|
|
246
|
+
"data-slot": "drawer-content",
|
|
247
|
+
className: cn(
|
|
248
|
+
"group/drawer-content bg-background fixed z-50 flex h-auto flex-col",
|
|
249
|
+
"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",
|
|
250
|
+
"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-lg data-[vaul-drawer-direction=bottom]:border-t",
|
|
251
|
+
"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",
|
|
252
|
+
"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",
|
|
253
|
+
className
|
|
254
|
+
),
|
|
255
|
+
...props,
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ jsx4("div", { className: "bg-muted mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block" }),
|
|
258
|
+
children
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
)
|
|
262
|
+
] });
|
|
263
|
+
}
|
|
264
|
+
function DrawerHeader({ className, ...props }) {
|
|
265
|
+
return /* @__PURE__ */ jsx4(
|
|
266
|
+
"div",
|
|
267
|
+
{
|
|
268
|
+
"data-slot": "drawer-header",
|
|
269
|
+
className: cn(
|
|
270
|
+
"flex flex-col 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",
|
|
271
|
+
className
|
|
272
|
+
),
|
|
273
|
+
...props
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
function DrawerTitle({
|
|
278
|
+
className,
|
|
279
|
+
...props
|
|
280
|
+
}) {
|
|
281
|
+
return /* @__PURE__ */ jsx4(
|
|
282
|
+
DrawerPrimitive.Title,
|
|
283
|
+
{
|
|
284
|
+
"data-slot": "drawer-title",
|
|
285
|
+
className: cn("text-foreground font-semibold", className),
|
|
286
|
+
...props
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/components/auth/user-button.tsx
|
|
292
|
+
import { signOut, useSession } from "next-auth/react";
|
|
293
|
+
import { LogOut, Settings, User, CreditCard, Moon, Sun } from "lucide-react";
|
|
294
|
+
import Link from "next/link";
|
|
295
|
+
|
|
296
|
+
// src/hooks/use-mobile.ts
|
|
297
|
+
import * as React from "react";
|
|
298
|
+
var MOBILE_BREAKPOINT = 768;
|
|
299
|
+
function useIsMobile() {
|
|
300
|
+
const [isMobile, setIsMobile] = React.useState(void 0);
|
|
301
|
+
React.useEffect(() => {
|
|
302
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
303
|
+
const onChange = () => {
|
|
304
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
305
|
+
};
|
|
306
|
+
mql.addEventListener("change", onChange);
|
|
307
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
308
|
+
return () => mql.removeEventListener("change", onChange);
|
|
309
|
+
}, []);
|
|
310
|
+
return !!isMobile;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// src/components/auth/user-button.tsx
|
|
314
|
+
import { useTheme } from "next-themes";
|
|
315
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
316
|
+
var defaultMenuItems = [
|
|
317
|
+
{
|
|
318
|
+
icon: User,
|
|
319
|
+
label: "Profile",
|
|
320
|
+
href: "/dashboard/settings/profile"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
icon: CreditCard,
|
|
324
|
+
label: "Billing",
|
|
325
|
+
href: "/dashboard/settings/billing"
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
icon: Settings,
|
|
329
|
+
label: "Settings",
|
|
330
|
+
href: "/dashboard/settings"
|
|
331
|
+
}
|
|
332
|
+
];
|
|
333
|
+
function UserButton({
|
|
334
|
+
menuItems = defaultMenuItems,
|
|
335
|
+
signInHref = "/login",
|
|
336
|
+
showThemeToggle = true
|
|
337
|
+
}) {
|
|
338
|
+
const { data: session } = useSession();
|
|
339
|
+
const isMobile = useIsMobile();
|
|
340
|
+
const { theme, setTheme } = useTheme();
|
|
341
|
+
if (!session?.user) {
|
|
342
|
+
return /* @__PURE__ */ jsx5(Button, { asChild: true, variant: "ghost", size: "sm", children: /* @__PURE__ */ jsx5(Link, { href: signInHref, children: "Sign in" }) });
|
|
343
|
+
}
|
|
344
|
+
const initials = session.user.name?.split(" ").map((n) => n[0]).join("").toUpperCase() || session.user.email?.[0]?.toUpperCase() || "U";
|
|
345
|
+
const toggleTheme = () => {
|
|
346
|
+
setTheme(theme === "dark" ? "light" : "dark");
|
|
347
|
+
};
|
|
348
|
+
const handleSignOut = () => {
|
|
349
|
+
signOut({ callbackUrl: "/" });
|
|
350
|
+
};
|
|
351
|
+
const AvatarButton = /* @__PURE__ */ jsx5(Button, { variant: "ghost", className: "relative h-8 w-8 rounded-full", children: /* @__PURE__ */ jsxs3(Avatar, { className: "h-8 w-8", children: [
|
|
352
|
+
/* @__PURE__ */ jsx5(
|
|
353
|
+
AvatarImage,
|
|
354
|
+
{
|
|
355
|
+
src: session.user.image || void 0,
|
|
356
|
+
alt: session.user.name || "User"
|
|
357
|
+
}
|
|
358
|
+
),
|
|
359
|
+
/* @__PURE__ */ jsx5(AvatarFallback, { className: "bg-primary/10 text-primary", children: initials })
|
|
360
|
+
] }) });
|
|
361
|
+
if (isMobile) {
|
|
362
|
+
return /* @__PURE__ */ jsxs3(Drawer, { children: [
|
|
363
|
+
/* @__PURE__ */ jsx5(DrawerTrigger, { asChild: true, children: AvatarButton }),
|
|
364
|
+
/* @__PURE__ */ jsxs3(DrawerContent, { children: [
|
|
365
|
+
/* @__PURE__ */ jsx5(DrawerHeader, { className: "text-left", children: /* @__PURE__ */ jsx5(DrawerTitle, { children: "Account" }) }),
|
|
366
|
+
/* @__PURE__ */ jsxs3("div", { className: "px-4 pb-8", children: [
|
|
367
|
+
/* @__PURE__ */ jsxs3("div", { className: "mb-6 flex items-center gap-3", children: [
|
|
368
|
+
/* @__PURE__ */ jsxs3(Avatar, { className: "h-12 w-12", children: [
|
|
369
|
+
/* @__PURE__ */ jsx5(
|
|
370
|
+
AvatarImage,
|
|
371
|
+
{
|
|
372
|
+
src: session.user.image || void 0,
|
|
373
|
+
alt: session.user.name || "User"
|
|
374
|
+
}
|
|
375
|
+
),
|
|
376
|
+
/* @__PURE__ */ jsx5(AvatarFallback, { className: "bg-primary/10 text-primary text-lg", children: initials })
|
|
377
|
+
] }),
|
|
378
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
379
|
+
/* @__PURE__ */ jsx5("p", { className: "font-medium", children: session.user.name || "User" }),
|
|
380
|
+
/* @__PURE__ */ jsx5("p", { className: "text-sm text-muted-foreground", children: session.user.email })
|
|
381
|
+
] })
|
|
382
|
+
] }),
|
|
383
|
+
/* @__PURE__ */ jsxs3("div", { className: "space-y-1", children: [
|
|
384
|
+
menuItems.map((item) => /* @__PURE__ */ jsx5(
|
|
385
|
+
Button,
|
|
386
|
+
{
|
|
387
|
+
variant: "ghost",
|
|
388
|
+
className: "w-full justify-start",
|
|
389
|
+
asChild: true,
|
|
390
|
+
children: /* @__PURE__ */ jsxs3(Link, { href: item.href, children: [
|
|
391
|
+
/* @__PURE__ */ jsx5(item.icon, { className: "mr-3 h-4 w-4" }),
|
|
392
|
+
item.label
|
|
393
|
+
] })
|
|
394
|
+
},
|
|
395
|
+
item.label
|
|
396
|
+
)),
|
|
397
|
+
showThemeToggle && /* @__PURE__ */ jsxs3(
|
|
398
|
+
Button,
|
|
399
|
+
{
|
|
400
|
+
variant: "ghost",
|
|
401
|
+
className: "w-full justify-start",
|
|
402
|
+
onClick: toggleTheme,
|
|
403
|
+
children: [
|
|
404
|
+
theme === "dark" ? /* @__PURE__ */ jsx5(Sun, { className: "mr-3 h-4 w-4" }) : /* @__PURE__ */ jsx5(Moon, { className: "mr-3 h-4 w-4" }),
|
|
405
|
+
theme === "dark" ? "Light mode" : "Dark mode"
|
|
406
|
+
]
|
|
407
|
+
}
|
|
408
|
+
),
|
|
409
|
+
/* @__PURE__ */ jsx5("div", { className: "my-2 border-t" }),
|
|
410
|
+
/* @__PURE__ */ jsxs3(
|
|
411
|
+
Button,
|
|
412
|
+
{
|
|
413
|
+
variant: "ghost",
|
|
414
|
+
className: "w-full justify-start text-destructive hover:text-destructive",
|
|
415
|
+
onClick: handleSignOut,
|
|
416
|
+
children: [
|
|
417
|
+
/* @__PURE__ */ jsx5(LogOut, { className: "mr-3 h-4 w-4" }),
|
|
418
|
+
"Sign out"
|
|
419
|
+
]
|
|
420
|
+
}
|
|
421
|
+
)
|
|
422
|
+
] })
|
|
423
|
+
] })
|
|
424
|
+
] })
|
|
425
|
+
] });
|
|
426
|
+
}
|
|
427
|
+
return /* @__PURE__ */ jsxs3(DropdownMenu, { children: [
|
|
428
|
+
/* @__PURE__ */ jsx5(DropdownMenuTrigger, { asChild: true, children: AvatarButton }),
|
|
429
|
+
/* @__PURE__ */ jsxs3(DropdownMenuContent, { className: "w-56", align: "end", forceMount: true, children: [
|
|
430
|
+
/* @__PURE__ */ jsx5(DropdownMenuLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs3("div", { className: "flex flex-col space-y-1", children: [
|
|
431
|
+
/* @__PURE__ */ jsx5("p", { className: "text-sm font-medium leading-none", children: session.user.name || "User" }),
|
|
432
|
+
/* @__PURE__ */ jsx5("p", { className: "text-xs leading-none text-muted-foreground", children: session.user.email })
|
|
433
|
+
] }) }),
|
|
434
|
+
/* @__PURE__ */ jsx5(DropdownMenuSeparator, {}),
|
|
435
|
+
menuItems.map((item) => /* @__PURE__ */ jsx5(DropdownMenuItem, { asChild: true, children: /* @__PURE__ */ jsxs3(Link, { href: item.href, children: [
|
|
436
|
+
/* @__PURE__ */ jsx5(item.icon, { className: "mr-2 h-4 w-4" }),
|
|
437
|
+
item.label
|
|
438
|
+
] }) }, item.label)),
|
|
439
|
+
showThemeToggle && /* @__PURE__ */ jsxs3(DropdownMenuItem, { onClick: toggleTheme, children: [
|
|
440
|
+
theme === "dark" ? /* @__PURE__ */ jsx5(Sun, { className: "mr-2 h-4 w-4" }) : /* @__PURE__ */ jsx5(Moon, { className: "mr-2 h-4 w-4" }),
|
|
441
|
+
theme === "dark" ? "Light mode" : "Dark mode"
|
|
442
|
+
] }),
|
|
443
|
+
/* @__PURE__ */ jsx5(DropdownMenuSeparator, {}),
|
|
444
|
+
/* @__PURE__ */ jsxs3(
|
|
445
|
+
DropdownMenuItem,
|
|
446
|
+
{
|
|
447
|
+
onClick: handleSignOut,
|
|
448
|
+
className: "text-destructive focus:text-destructive",
|
|
449
|
+
children: [
|
|
450
|
+
/* @__PURE__ */ jsx5(LogOut, { className: "mr-2 h-4 w-4" }),
|
|
451
|
+
"Sign out"
|
|
452
|
+
]
|
|
453
|
+
}
|
|
454
|
+
)
|
|
455
|
+
] })
|
|
456
|
+
] });
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// src/components/ui/input.tsx
|
|
460
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
461
|
+
function Input({ className, type, ...props }) {
|
|
462
|
+
return /* @__PURE__ */ jsx6(
|
|
463
|
+
"input",
|
|
464
|
+
{
|
|
465
|
+
type,
|
|
466
|
+
"data-slot": "input",
|
|
467
|
+
className: cn(
|
|
468
|
+
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
469
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
470
|
+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
471
|
+
className
|
|
472
|
+
),
|
|
473
|
+
...props
|
|
474
|
+
}
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// src/components/ui/label.tsx
|
|
479
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
480
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
481
|
+
function Label2({
|
|
482
|
+
className,
|
|
483
|
+
...props
|
|
484
|
+
}) {
|
|
485
|
+
return /* @__PURE__ */ jsx7(
|
|
486
|
+
LabelPrimitive.Root,
|
|
487
|
+
{
|
|
488
|
+
"data-slot": "label",
|
|
489
|
+
className: cn(
|
|
490
|
+
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
491
|
+
className
|
|
492
|
+
),
|
|
493
|
+
...props
|
|
494
|
+
}
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// src/components/ui/separator.tsx
|
|
499
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
500
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
501
|
+
function Separator2({
|
|
502
|
+
className,
|
|
503
|
+
orientation = "horizontal",
|
|
504
|
+
decorative = true,
|
|
505
|
+
...props
|
|
506
|
+
}) {
|
|
507
|
+
return /* @__PURE__ */ jsx8(
|
|
508
|
+
SeparatorPrimitive.Root,
|
|
509
|
+
{
|
|
510
|
+
"data-slot": "separator",
|
|
511
|
+
decorative,
|
|
512
|
+
orientation,
|
|
513
|
+
className: cn(
|
|
514
|
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
|
515
|
+
className
|
|
516
|
+
),
|
|
517
|
+
...props
|
|
518
|
+
}
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// src/components/auth/auth-form.tsx
|
|
523
|
+
import { signIn } from "next-auth/react";
|
|
524
|
+
import { useState as useState2 } from "react";
|
|
525
|
+
import { Loader2 } from "lucide-react";
|
|
526
|
+
import Link2 from "next/link";
|
|
527
|
+
import { useSearchParams } from "next/navigation";
|
|
528
|
+
import { Fragment, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
529
|
+
function AuthForm({
|
|
530
|
+
mode,
|
|
531
|
+
providers = ["google", "email"],
|
|
532
|
+
signupHref = "/signup",
|
|
533
|
+
loginHref = "/login",
|
|
534
|
+
verifyRequestHref = "/verify-request",
|
|
535
|
+
defaultCallbackUrl = "/dashboard"
|
|
536
|
+
}) {
|
|
537
|
+
const [email, setEmail] = useState2("");
|
|
538
|
+
const [isLoading, setIsLoading] = useState2(false);
|
|
539
|
+
const [isGoogleLoading, setIsGoogleLoading] = useState2(false);
|
|
540
|
+
const [isGithubLoading, setIsGithubLoading] = useState2(false);
|
|
541
|
+
const [error, setError] = useState2("");
|
|
542
|
+
const searchParams = useSearchParams();
|
|
543
|
+
const callbackUrl = searchParams.get("callbackUrl") || defaultCallbackUrl;
|
|
544
|
+
const isLogin = mode === "login";
|
|
545
|
+
const showGoogle = providers.includes("google");
|
|
546
|
+
const showGithub = providers.includes("github");
|
|
547
|
+
const showEmail = providers.includes("email");
|
|
548
|
+
const handleEmailSubmit = async (e) => {
|
|
549
|
+
e.preventDefault();
|
|
550
|
+
setIsLoading(true);
|
|
551
|
+
setError("");
|
|
552
|
+
try {
|
|
553
|
+
const result = await signIn("resend", {
|
|
554
|
+
email,
|
|
555
|
+
callbackUrl,
|
|
556
|
+
redirect: false
|
|
557
|
+
});
|
|
558
|
+
if (result?.error) {
|
|
559
|
+
setError("Failed to send magic link. Please try again.");
|
|
560
|
+
} else {
|
|
561
|
+
window.location.href = verifyRequestHref;
|
|
562
|
+
}
|
|
563
|
+
} catch {
|
|
564
|
+
setError("Something went wrong");
|
|
565
|
+
} finally {
|
|
566
|
+
setIsLoading(false);
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
const handleGoogleSignIn = async () => {
|
|
570
|
+
setIsGoogleLoading(true);
|
|
571
|
+
try {
|
|
572
|
+
await signIn("google", {
|
|
573
|
+
callbackUrl
|
|
574
|
+
});
|
|
575
|
+
} catch (error2) {
|
|
576
|
+
console.error("Google sign in error:", error2);
|
|
577
|
+
} finally {
|
|
578
|
+
setIsGoogleLoading(false);
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
const handleGithubSignIn = async () => {
|
|
582
|
+
setIsGithubLoading(true);
|
|
583
|
+
try {
|
|
584
|
+
await signIn("github", {
|
|
585
|
+
callbackUrl
|
|
586
|
+
});
|
|
587
|
+
} catch (error2) {
|
|
588
|
+
console.error("GitHub sign in error:", error2);
|
|
589
|
+
} finally {
|
|
590
|
+
setIsGithubLoading(false);
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
return /* @__PURE__ */ jsxs4("div", { className: "space-y-6", children: [
|
|
594
|
+
/* @__PURE__ */ jsxs4("div", { className: "space-y-2 text-center", children: [
|
|
595
|
+
/* @__PURE__ */ jsx9("h1", { className: "text-2xl font-semibold tracking-tight", children: isLogin ? "Welcome back" : "Create an account" }),
|
|
596
|
+
/* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: isLogin ? "Sign in to your account to continue" : "Enter your email to get started" })
|
|
597
|
+
] }),
|
|
598
|
+
error && /* @__PURE__ */ jsx9("div", { className: "p-3 text-sm text-destructive bg-destructive/10 rounded-md", children: error }),
|
|
599
|
+
showGoogle && /* @__PURE__ */ jsxs4(
|
|
600
|
+
Button,
|
|
601
|
+
{
|
|
602
|
+
type: "button",
|
|
603
|
+
variant: "outline",
|
|
604
|
+
className: "w-full",
|
|
605
|
+
onClick: handleGoogleSignIn,
|
|
606
|
+
disabled: isGoogleLoading,
|
|
607
|
+
children: [
|
|
608
|
+
isGoogleLoading ? /* @__PURE__ */ jsx9(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsxs4("svg", { className: "mr-2 h-4 w-4", viewBox: "0 0 24 24", children: [
|
|
609
|
+
/* @__PURE__ */ jsx9(
|
|
610
|
+
"path",
|
|
611
|
+
{
|
|
612
|
+
d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z",
|
|
613
|
+
fill: "#4285F4"
|
|
614
|
+
}
|
|
615
|
+
),
|
|
616
|
+
/* @__PURE__ */ jsx9(
|
|
617
|
+
"path",
|
|
618
|
+
{
|
|
619
|
+
d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z",
|
|
620
|
+
fill: "#34A853"
|
|
621
|
+
}
|
|
622
|
+
),
|
|
623
|
+
/* @__PURE__ */ jsx9(
|
|
624
|
+
"path",
|
|
625
|
+
{
|
|
626
|
+
d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z",
|
|
627
|
+
fill: "#FBBC05"
|
|
628
|
+
}
|
|
629
|
+
),
|
|
630
|
+
/* @__PURE__ */ jsx9(
|
|
631
|
+
"path",
|
|
632
|
+
{
|
|
633
|
+
d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z",
|
|
634
|
+
fill: "#EA4335"
|
|
635
|
+
}
|
|
636
|
+
)
|
|
637
|
+
] }),
|
|
638
|
+
"Continue with Google"
|
|
639
|
+
]
|
|
640
|
+
}
|
|
641
|
+
),
|
|
642
|
+
showGithub && /* @__PURE__ */ jsxs4(
|
|
643
|
+
Button,
|
|
644
|
+
{
|
|
645
|
+
type: "button",
|
|
646
|
+
variant: "outline",
|
|
647
|
+
className: "w-full",
|
|
648
|
+
onClick: handleGithubSignIn,
|
|
649
|
+
disabled: isGithubLoading,
|
|
650
|
+
children: [
|
|
651
|
+
isGithubLoading ? /* @__PURE__ */ jsx9(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx9("svg", { className: "mr-2 h-4 w-4", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx9("path", { d: "M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" }) }),
|
|
652
|
+
"Continue with GitHub"
|
|
653
|
+
]
|
|
654
|
+
}
|
|
655
|
+
),
|
|
656
|
+
showEmail && (showGoogle || showGithub) && /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
|
|
657
|
+
/* @__PURE__ */ jsx9("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx9(Separator2, { className: "w-full" }) }),
|
|
658
|
+
/* @__PURE__ */ jsx9("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx9("span", { className: "bg-background px-2 text-muted-foreground", children: "Or continue with email" }) })
|
|
659
|
+
] }),
|
|
660
|
+
showEmail && /* @__PURE__ */ jsxs4("form", { onSubmit: handleEmailSubmit, className: "space-y-4", children: [
|
|
661
|
+
/* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
|
|
662
|
+
/* @__PURE__ */ jsx9(Label2, { htmlFor: "email", children: "Email" }),
|
|
663
|
+
/* @__PURE__ */ jsx9(
|
|
664
|
+
Input,
|
|
665
|
+
{
|
|
666
|
+
id: "email",
|
|
667
|
+
type: "email",
|
|
668
|
+
placeholder: "name@example.com",
|
|
669
|
+
value: email,
|
|
670
|
+
onChange: (e) => setEmail(e.target.value),
|
|
671
|
+
required: true,
|
|
672
|
+
disabled: isLoading
|
|
673
|
+
}
|
|
674
|
+
)
|
|
675
|
+
] }),
|
|
676
|
+
/* @__PURE__ */ jsx9(Button, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
677
|
+
/* @__PURE__ */ jsx9(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
678
|
+
"Sending magic link..."
|
|
679
|
+
] }) : "Send magic link" })
|
|
680
|
+
] }),
|
|
681
|
+
/* @__PURE__ */ jsx9("p", { className: "text-center text-sm text-muted-foreground", children: isLogin ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
682
|
+
"Don't have an account?",
|
|
683
|
+
" ",
|
|
684
|
+
/* @__PURE__ */ jsx9(Link2, { href: signupHref, className: "text-primary hover:underline", children: "Sign up" })
|
|
685
|
+
] }) : /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
686
|
+
"Already have an account?",
|
|
687
|
+
" ",
|
|
688
|
+
/* @__PURE__ */ jsx9(Link2, { href: loginHref, className: "text-primary hover:underline", children: "Sign in" })
|
|
689
|
+
] }) })
|
|
690
|
+
] });
|
|
691
|
+
}
|
|
692
|
+
export {
|
|
693
|
+
AuthForm,
|
|
694
|
+
UserButton
|
|
695
|
+
};
|
|
696
|
+
//# sourceMappingURL=index.mjs.map
|