nextworks 0.1.0-alpha.11 → 0.1.0-alpha.14
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/README.md +20 -9
- package/dist/kits/auth-core/.nextworks/docs/AUTH_CORE_README.md +3 -3
- package/dist/kits/auth-core/.nextworks/docs/AUTH_QUICKSTART.md +264 -244
- package/dist/kits/auth-core/app/(protected)/settings/profile/profile-form.tsx +120 -114
- package/dist/kits/auth-core/app/api/auth/forgot-password/route.ts +116 -114
- package/dist/kits/auth-core/app/api/auth/reset-password/route.ts +66 -63
- package/dist/kits/auth-core/app/api/auth/send-verify-email/route.ts +1 -1
- package/dist/kits/auth-core/app/api/users/[id]/route.ts +134 -127
- package/dist/kits/auth-core/app/auth/reset-password/page.tsx +186 -187
- package/dist/kits/auth-core/components/auth/dashboard.tsx +25 -2
- package/dist/kits/auth-core/components/auth/forgot-password-form.tsx +90 -90
- package/dist/kits/auth-core/components/auth/login-form.tsx +492 -467
- package/dist/kits/auth-core/components/auth/signup-form.tsx +28 -29
- package/dist/kits/auth-core/lib/auth.ts +46 -15
- package/dist/kits/auth-core/lib/forms/map-errors.ts +37 -11
- package/dist/kits/auth-core/lib/server/result.ts +45 -45
- package/dist/kits/auth-core/lib/validation/forms.ts +1 -2
- package/dist/kits/auth-core/package-deps.json +4 -2
- package/dist/kits/auth-core/types/next-auth.d.ts +1 -1
- package/dist/kits/blocks/.nextworks/docs/BLOCKS_QUICKSTART.md +2 -8
- package/dist/kits/blocks/.nextworks/docs/THEME_GUIDE.md +18 -1
- package/dist/kits/blocks/app/templates/productlaunch/page.tsx +0 -2
- package/dist/kits/blocks/components/sections/FAQ.tsx +0 -1
- package/dist/kits/blocks/components/sections/Newsletter.tsx +2 -2
- package/dist/kits/blocks/components/ui/switch.tsx +78 -78
- package/dist/kits/blocks/components/ui/theme-selector.tsx +1 -1
- package/dist/kits/blocks/lib/themes.ts +1 -0
- package/dist/kits/blocks/package-deps.json +4 -4
- package/dist/kits/data/.nextworks/docs/DATA_QUICKSTART.md +128 -112
- package/dist/kits/data/.nextworks/docs/DATA_README.md +2 -1
- package/dist/kits/data/app/api/posts/[id]/route.ts +83 -83
- package/dist/kits/data/app/api/posts/route.ts +136 -138
- package/dist/kits/data/app/api/seed-demo/route.ts +1 -2
- package/dist/kits/data/app/api/users/[id]/route.ts +29 -17
- package/dist/kits/data/app/api/users/check-email/route.ts +1 -1
- package/dist/kits/data/app/api/users/check-unique/route.ts +30 -27
- package/dist/kits/data/app/api/users/route.ts +0 -2
- package/dist/kits/data/app/examples/demo/create-post-form.tsx +108 -106
- package/dist/kits/data/app/examples/demo/page.tsx +2 -1
- package/dist/kits/data/app/examples/demo/seed-demo-button.tsx +1 -1
- package/dist/kits/data/components/admin/posts-manager.tsx +727 -719
- package/dist/kits/data/components/admin/users-manager.tsx +435 -432
- package/dist/kits/data/lib/server/result.ts +5 -2
- package/dist/kits/data/package-deps.json +1 -1
- package/dist/kits/data/scripts/seed-demo.mjs +1 -2
- package/dist/kits/forms/app/api/wizard/route.ts +76 -71
- package/dist/kits/forms/app/examples/forms/server-action/page.tsx +78 -71
- package/dist/kits/forms/components/hooks/useCheckUnique.ts +85 -79
- package/dist/kits/forms/components/ui/form/form-control.tsx +28 -28
- package/dist/kits/forms/components/ui/form/form-description.tsx +23 -22
- package/dist/kits/forms/components/ui/form/form-item.tsx +21 -21
- package/dist/kits/forms/components/ui/form/form-label.tsx +24 -24
- package/dist/kits/forms/components/ui/form/form-message.tsx +28 -29
- package/dist/kits/forms/components/ui/switch.tsx +78 -78
- package/dist/kits/forms/lib/forms/map-errors.ts +1 -1
- package/dist/kits/forms/lib/validation/forms.ts +1 -2
- package/package.json +1 -1
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { cn } from "@/lib/utils";
|
|
5
|
-
import { FormItemContext } from "./context";
|
|
6
|
-
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export const FormItem = React.forwardRef<HTMLDivElement, FormItemProps>(
|
|
11
|
-
({ className, ...props }, ref) => {
|
|
12
|
-
const id = React.useId();
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<FormItemContext.Provider value={{ id }}>
|
|
16
|
-
<div ref={ref} className={cn("space-y-2", className)} {...props} />
|
|
17
|
-
</FormItemContext.Provider>
|
|
18
|
-
);
|
|
19
|
-
},
|
|
20
|
-
);
|
|
21
|
-
FormItem.displayName = "FormItem";
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
import { FormItemContext } from "./context";
|
|
6
|
+
|
|
7
|
+
export type FormItemProps = React.HTMLAttributes<HTMLDivElement>;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export const FormItem = React.forwardRef<HTMLDivElement, FormItemProps>(
|
|
11
|
+
({ className, ...props }, ref) => {
|
|
12
|
+
const id = React.useId();
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<FormItemContext.Provider value={{ id }}>
|
|
16
|
+
<div ref={ref} className={cn("space-y-2", className)} {...props} />
|
|
17
|
+
</FormItemContext.Provider>
|
|
18
|
+
);
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
FormItem.displayName = "FormItem";
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { Label } from "@/components/ui/label";
|
|
5
|
-
import { useFormField } from "./context";
|
|
6
|
-
import { cn } from "@/lib/utils";
|
|
7
|
-
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
export const FormLabel = React.forwardRef<
|
|
11
|
-
React.ElementRef<typeof Label>,
|
|
12
|
-
FormLabelProps
|
|
13
|
-
>(({ className, ...props }, ref) => {
|
|
14
|
-
const { formItemId } = useFormField();
|
|
15
|
-
return (
|
|
16
|
-
<Label
|
|
17
|
-
ref={ref}
|
|
18
|
-
htmlFor={formItemId}
|
|
19
|
-
className={cn(className)}
|
|
20
|
-
{...props}
|
|
21
|
-
/>
|
|
22
|
-
);
|
|
23
|
-
});
|
|
24
|
-
FormLabel.displayName = "FormLabel";
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Label } from "@/components/ui/label";
|
|
5
|
+
import { useFormField } from "./context";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
export type FormLabelProps = React.ComponentProps<typeof Label>;
|
|
9
|
+
|
|
10
|
+
export const FormLabel = React.forwardRef<
|
|
11
|
+
React.ElementRef<typeof Label>,
|
|
12
|
+
FormLabelProps
|
|
13
|
+
>(({ className, ...props }, ref) => {
|
|
14
|
+
const { formItemId } = useFormField();
|
|
15
|
+
return (
|
|
16
|
+
<Label
|
|
17
|
+
ref={ref}
|
|
18
|
+
htmlFor={formItemId}
|
|
19
|
+
className={cn(className)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
FormLabel.displayName = "FormLabel";
|
|
@@ -1,29 +1,28 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { useFormField } from "./context";
|
|
5
|
-
import { cn } from "@/lib/utils";
|
|
6
|
-
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
};
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useFormField } from "./context";
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
export type FormMessageProps = React.HTMLAttributes<HTMLParagraphElement>;
|
|
8
|
+
|
|
9
|
+
export const FormMessage = ({
|
|
10
|
+
className,
|
|
11
|
+
children,
|
|
12
|
+
...props
|
|
13
|
+
}: FormMessageProps) => {
|
|
14
|
+
const { error, formMessageId } = useFormField();
|
|
15
|
+
const body = error ? String(error.message || children) : children;
|
|
16
|
+
|
|
17
|
+
if (!body) return null;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<p
|
|
21
|
+
id={formMessageId}
|
|
22
|
+
className={cn("text-xs text-destructive", className)}
|
|
23
|
+
{...props}
|
|
24
|
+
>
|
|
25
|
+
{body}
|
|
26
|
+
</p>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cn } from "@/lib/utils";
|
|
3
|
-
|
|
4
|
-
export type SwitchProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
5
|
-
isLoading?: boolean;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
|
|
9
|
-
({ className, isLoading, disabled, ...props }, ref) => {
|
|
10
|
-
const checked =
|
|
11
|
-
const isDisabled = !!disabled || !!isLoading;
|
|
12
|
-
return (
|
|
13
|
-
<label
|
|
14
|
-
className={cn(
|
|
15
|
-
"focus-within:ring-offset-background inline-flex items-center rounded-full focus-within:ring-2 focus-within:ring-[var(--ring)] focus-within:ring-offset-2",
|
|
16
|
-
isDisabled ? "cursor-not-allowed opacity-80" : "cursor-pointer",
|
|
17
|
-
className,
|
|
18
|
-
)}
|
|
19
|
-
>
|
|
20
|
-
<input
|
|
21
|
-
type="checkbox"
|
|
22
|
-
role="switch"
|
|
23
|
-
ref={ref}
|
|
24
|
-
className="sr-only"
|
|
25
|
-
disabled={isDisabled}
|
|
26
|
-
aria-busy={isLoading ? "true" : undefined}
|
|
27
|
-
{...
|
|
28
|
-
/>
|
|
29
|
-
<span
|
|
30
|
-
aria-hidden
|
|
31
|
-
className={cn(
|
|
32
|
-
"relative inline-flex h-6 w-11 flex-shrink-0 rounded-full transition-colors duration-200",
|
|
33
|
-
checked ? "bg-[var(--primary)]" : "bg-[var(--primary)]/80",
|
|
34
|
-
)}
|
|
35
|
-
>
|
|
36
|
-
<span
|
|
37
|
-
className={cn(
|
|
38
|
-
// Thumb should adjust for theme to guarantee contrast
|
|
39
|
-
"absolute top-0.5 left-0.5 h-5 w-5 transform rounded-full bg-[var(--switch-thumb)] shadow-md transition-transform duration-200 ease-in-out",
|
|
40
|
-
checked ? "translate-x-5" : "translate-x-0",
|
|
41
|
-
)}
|
|
42
|
-
/>
|
|
43
|
-
|
|
44
|
-
{/* Loading indicator centered inside the switch when isLoading */}
|
|
45
|
-
{isLoading && (
|
|
46
|
-
<span className="absolute inset-0 flex items-center justify-center">
|
|
47
|
-
<svg
|
|
48
|
-
className="h-4 w-4 animate-spin text-white"
|
|
49
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
50
|
-
fill="none"
|
|
51
|
-
viewBox="0 0 24 24"
|
|
52
|
-
aria-hidden
|
|
53
|
-
>
|
|
54
|
-
<circle
|
|
55
|
-
className="opacity-25"
|
|
56
|
-
cx="12"
|
|
57
|
-
cy="12"
|
|
58
|
-
r="10"
|
|
59
|
-
stroke="currentColor"
|
|
60
|
-
strokeWidth="4"
|
|
61
|
-
/>
|
|
62
|
-
<path
|
|
63
|
-
className="opacity-75"
|
|
64
|
-
fill="currentColor"
|
|
65
|
-
d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"
|
|
66
|
-
/>
|
|
67
|
-
</svg>
|
|
68
|
-
</span>
|
|
69
|
-
)}
|
|
70
|
-
</span>
|
|
71
|
-
</label>
|
|
72
|
-
);
|
|
73
|
-
},
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
Switch.displayName = "Switch";
|
|
77
|
-
|
|
78
|
-
export { Switch };
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
export type SwitchProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
5
|
+
isLoading?: boolean;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
|
|
9
|
+
({ className, isLoading, disabled, ...props }, ref) => {
|
|
10
|
+
const checked = typeof props.checked === "boolean" ? props.checked : false;
|
|
11
|
+
const isDisabled = !!disabled || !!isLoading;
|
|
12
|
+
return (
|
|
13
|
+
<label
|
|
14
|
+
className={cn(
|
|
15
|
+
"focus-within:ring-offset-background inline-flex items-center rounded-full focus-within:ring-2 focus-within:ring-[var(--ring)] focus-within:ring-offset-2",
|
|
16
|
+
isDisabled ? "cursor-not-allowed opacity-80" : "cursor-pointer",
|
|
17
|
+
className,
|
|
18
|
+
)}
|
|
19
|
+
>
|
|
20
|
+
<input
|
|
21
|
+
type="checkbox"
|
|
22
|
+
role="switch"
|
|
23
|
+
ref={ref}
|
|
24
|
+
className="sr-only"
|
|
25
|
+
disabled={isDisabled}
|
|
26
|
+
aria-busy={isLoading ? "true" : undefined}
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
<span
|
|
30
|
+
aria-hidden
|
|
31
|
+
className={cn(
|
|
32
|
+
"relative inline-flex h-6 w-11 flex-shrink-0 rounded-full transition-colors duration-200",
|
|
33
|
+
checked ? "bg-[var(--primary)]" : "bg-[var(--primary)]/80",
|
|
34
|
+
)}
|
|
35
|
+
>
|
|
36
|
+
<span
|
|
37
|
+
className={cn(
|
|
38
|
+
// Thumb should adjust for theme to guarantee contrast
|
|
39
|
+
"absolute top-0.5 left-0.5 h-5 w-5 transform rounded-full bg-[var(--switch-thumb)] shadow-md transition-transform duration-200 ease-in-out",
|
|
40
|
+
checked ? "translate-x-5" : "translate-x-0",
|
|
41
|
+
)}
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
{/* Loading indicator centered inside the switch when isLoading */}
|
|
45
|
+
{isLoading && (
|
|
46
|
+
<span className="absolute inset-0 flex items-center justify-center">
|
|
47
|
+
<svg
|
|
48
|
+
className="h-4 w-4 animate-spin text-white"
|
|
49
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
50
|
+
fill="none"
|
|
51
|
+
viewBox="0 0 24 24"
|
|
52
|
+
aria-hidden
|
|
53
|
+
>
|
|
54
|
+
<circle
|
|
55
|
+
className="opacity-25"
|
|
56
|
+
cx="12"
|
|
57
|
+
cy="12"
|
|
58
|
+
r="10"
|
|
59
|
+
stroke="currentColor"
|
|
60
|
+
strokeWidth="4"
|
|
61
|
+
/>
|
|
62
|
+
<path
|
|
63
|
+
className="opacity-75"
|
|
64
|
+
fill="currentColor"
|
|
65
|
+
d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"
|
|
66
|
+
/>
|
|
67
|
+
</svg>
|
|
68
|
+
</span>
|
|
69
|
+
)}
|
|
70
|
+
</span>
|
|
71
|
+
</label>
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
Switch.displayName = "Switch";
|
|
77
|
+
|
|
78
|
+
export { Switch };
|
|
@@ -3,7 +3,7 @@ import type { ApiResult } from "@/lib/server/result";
|
|
|
3
3
|
|
|
4
4
|
export function mapApiErrorsToForm<TFieldValues extends FieldValues>(
|
|
5
5
|
form: UseFormReturn<TFieldValues>,
|
|
6
|
-
result: ApiResult<
|
|
6
|
+
result: ApiResult<unknown>,
|
|
7
7
|
options?: { formKey?: string },
|
|
8
8
|
): string | undefined {
|
|
9
9
|
if (!result || result.success) return undefined;
|
|
@@ -60,8 +60,7 @@ export const userUpdateSchema = z.object({
|
|
|
60
60
|
password: z
|
|
61
61
|
.string()
|
|
62
62
|
.min(6, "Password must be at least 6 characters")
|
|
63
|
-
.optional()
|
|
64
|
-
.or(z.literal("")),
|
|
63
|
+
.optional(),
|
|
65
64
|
emailVerified: z
|
|
66
65
|
.union([z.date(), z.string().transform((s) => new Date(s)), z.null()])
|
|
67
66
|
.optional(),
|