@questpie/admin 0.0.1

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 (203) hide show
  1. package/.turbo/turbo-build.log +108 -0
  2. package/CHANGELOG.md +10 -0
  3. package/README.md +556 -0
  4. package/STATUS.md +917 -0
  5. package/VALIDATION.md +602 -0
  6. package/components.json +24 -0
  7. package/dist/__tests__/setup.mjs +38 -0
  8. package/dist/__tests__/test-utils.mjs +45 -0
  9. package/dist/__tests__/vitest.d.mjs +3 -0
  10. package/dist/components/admin-app.mjs +69 -0
  11. package/dist/components/fields/array-field.mjs +190 -0
  12. package/dist/components/fields/checkbox-field.mjs +34 -0
  13. package/dist/components/fields/custom-field.mjs +32 -0
  14. package/dist/components/fields/date-field.mjs +41 -0
  15. package/dist/components/fields/datetime-field.mjs +42 -0
  16. package/dist/components/fields/email-field.mjs +37 -0
  17. package/dist/components/fields/embedded-collection.mjs +253 -0
  18. package/dist/components/fields/field-types.mjs +1 -0
  19. package/dist/components/fields/field-utils.mjs +10 -0
  20. package/dist/components/fields/field-wrapper.mjs +34 -0
  21. package/dist/components/fields/index.mjs +23 -0
  22. package/dist/components/fields/json-field.mjs +243 -0
  23. package/dist/components/fields/locale-badge.mjs +16 -0
  24. package/dist/components/fields/number-field.mjs +39 -0
  25. package/dist/components/fields/password-field.mjs +37 -0
  26. package/dist/components/fields/relation-field.mjs +104 -0
  27. package/dist/components/fields/relation-picker.mjs +229 -0
  28. package/dist/components/fields/relation-select.mjs +188 -0
  29. package/dist/components/fields/rich-text-editor/index.mjs +897 -0
  30. package/dist/components/fields/select-field.mjs +41 -0
  31. package/dist/components/fields/switch-field.mjs +34 -0
  32. package/dist/components/fields/text-field.mjs +38 -0
  33. package/dist/components/fields/textarea-field.mjs +38 -0
  34. package/dist/components/index.mjs +59 -0
  35. package/dist/components/primitives/checkbox-input.mjs +127 -0
  36. package/dist/components/primitives/date-input.mjs +303 -0
  37. package/dist/components/primitives/index.mjs +12 -0
  38. package/dist/components/primitives/number-input.mjs +104 -0
  39. package/dist/components/primitives/select-input.mjs +177 -0
  40. package/dist/components/primitives/tag-input.mjs +135 -0
  41. package/dist/components/primitives/text-input.mjs +39 -0
  42. package/dist/components/primitives/textarea-input.mjs +37 -0
  43. package/dist/components/primitives/toggle-input.mjs +31 -0
  44. package/dist/components/primitives/types.mjs +12 -0
  45. package/dist/components/ui/accordion.mjs +55 -0
  46. package/dist/components/ui/avatar.mjs +54 -0
  47. package/dist/components/ui/badge.mjs +34 -0
  48. package/dist/components/ui/button.mjs +48 -0
  49. package/dist/components/ui/card.mjs +58 -0
  50. package/dist/components/ui/checkbox.mjs +21 -0
  51. package/dist/components/ui/combobox.mjs +163 -0
  52. package/dist/components/ui/dialog.mjs +95 -0
  53. package/dist/components/ui/dropdown-menu.mjs +138 -0
  54. package/dist/components/ui/field.mjs +113 -0
  55. package/dist/components/ui/input-group.mjs +82 -0
  56. package/dist/components/ui/input.mjs +17 -0
  57. package/dist/components/ui/label.mjs +15 -0
  58. package/dist/components/ui/popover.mjs +56 -0
  59. package/dist/components/ui/scroll-area.mjs +38 -0
  60. package/dist/components/ui/select.mjs +100 -0
  61. package/dist/components/ui/separator.mjs +16 -0
  62. package/dist/components/ui/sheet.mjs +90 -0
  63. package/dist/components/ui/sidebar.mjs +387 -0
  64. package/dist/components/ui/skeleton.mjs +14 -0
  65. package/dist/components/ui/spinner.mjs +16 -0
  66. package/dist/components/ui/switch.mjs +22 -0
  67. package/dist/components/ui/table.mjs +68 -0
  68. package/dist/components/ui/tabs.mjs +48 -0
  69. package/dist/components/ui/textarea.mjs +15 -0
  70. package/dist/components/ui/tooltip.mjs +44 -0
  71. package/dist/config/component-registry.mjs +38 -0
  72. package/dist/config/index.mjs +129 -0
  73. package/dist/hooks/admin-provider.mjs +70 -0
  74. package/dist/hooks/index.mjs +7 -0
  75. package/dist/hooks/store.mjs +178 -0
  76. package/dist/hooks/use-auth.mjs +76 -0
  77. package/dist/hooks/use-collection-db.mjs +146 -0
  78. package/dist/hooks/use-collection.mjs +112 -0
  79. package/dist/hooks/use-global.mjs +46 -0
  80. package/dist/hooks/use-mobile.mjs +20 -0
  81. package/dist/lib/utils.mjs +10 -0
  82. package/dist/styles/index.css +336 -0
  83. package/dist/styles/index.mjs +1 -0
  84. package/dist/utils/index.mjs +9 -0
  85. package/dist/views/auth/auth-layout.mjs +52 -0
  86. package/dist/views/auth/forgot-password-form.mjs +148 -0
  87. package/dist/views/auth/index.mjs +6 -0
  88. package/dist/views/auth/login-form.mjs +156 -0
  89. package/dist/views/auth/reset-password-form.mjs +184 -0
  90. package/dist/views/collection/auto-form-fields.mjs +525 -0
  91. package/dist/views/collection/collection-form.mjs +91 -0
  92. package/dist/views/collection/collection-list.mjs +76 -0
  93. package/dist/views/collection/form-field.mjs +42 -0
  94. package/dist/views/collection/index.mjs +6 -0
  95. package/dist/views/common/index.mjs +4 -0
  96. package/dist/views/common/locale-switcher.mjs +39 -0
  97. package/dist/views/common/version-history.mjs +272 -0
  98. package/dist/views/index.mjs +9 -0
  99. package/dist/views/layout/admin-layout.mjs +40 -0
  100. package/dist/views/layout/admin-router.mjs +95 -0
  101. package/dist/views/layout/admin-sidebar.mjs +63 -0
  102. package/dist/views/layout/index.mjs +5 -0
  103. package/package.json +276 -0
  104. package/src/__tests__/setup.ts +44 -0
  105. package/src/__tests__/test-utils.tsx +49 -0
  106. package/src/__tests__/vitest.d.ts +9 -0
  107. package/src/components/admin-app.tsx +221 -0
  108. package/src/components/fields/array-field.tsx +237 -0
  109. package/src/components/fields/checkbox-field.tsx +47 -0
  110. package/src/components/fields/custom-field.tsx +50 -0
  111. package/src/components/fields/date-field.tsx +65 -0
  112. package/src/components/fields/datetime-field.tsx +67 -0
  113. package/src/components/fields/email-field.tsx +51 -0
  114. package/src/components/fields/embedded-collection.tsx +315 -0
  115. package/src/components/fields/field-types.ts +162 -0
  116. package/src/components/fields/field-utils.ts +6 -0
  117. package/src/components/fields/field-wrapper.tsx +52 -0
  118. package/src/components/fields/index.ts +66 -0
  119. package/src/components/fields/json-field.tsx +440 -0
  120. package/src/components/fields/locale-badge.tsx +15 -0
  121. package/src/components/fields/number-field.tsx +57 -0
  122. package/src/components/fields/password-field.tsx +51 -0
  123. package/src/components/fields/relation-field.tsx +243 -0
  124. package/src/components/fields/relation-picker.tsx +402 -0
  125. package/src/components/fields/relation-select.tsx +327 -0
  126. package/src/components/fields/rich-text-editor/index.tsx +1337 -0
  127. package/src/components/fields/select-field.tsx +61 -0
  128. package/src/components/fields/switch-field.tsx +47 -0
  129. package/src/components/fields/text-field.tsx +55 -0
  130. package/src/components/fields/textarea-field.tsx +55 -0
  131. package/src/components/index.ts +40 -0
  132. package/src/components/primitives/checkbox-input.tsx +193 -0
  133. package/src/components/primitives/date-input.tsx +401 -0
  134. package/src/components/primitives/index.ts +24 -0
  135. package/src/components/primitives/number-input.tsx +132 -0
  136. package/src/components/primitives/select-input.tsx +296 -0
  137. package/src/components/primitives/tag-input.tsx +200 -0
  138. package/src/components/primitives/text-input.tsx +49 -0
  139. package/src/components/primitives/textarea-input.tsx +46 -0
  140. package/src/components/primitives/toggle-input.tsx +36 -0
  141. package/src/components/primitives/types.ts +235 -0
  142. package/src/components/ui/accordion.tsx +72 -0
  143. package/src/components/ui/avatar.tsx +106 -0
  144. package/src/components/ui/badge.tsx +48 -0
  145. package/src/components/ui/button.tsx +53 -0
  146. package/src/components/ui/card.tsx +94 -0
  147. package/src/components/ui/checkbox.tsx +27 -0
  148. package/src/components/ui/combobox.tsx +290 -0
  149. package/src/components/ui/dialog.tsx +151 -0
  150. package/src/components/ui/dropdown-menu.tsx +254 -0
  151. package/src/components/ui/field.tsx +227 -0
  152. package/src/components/ui/input-group.tsx +149 -0
  153. package/src/components/ui/input.tsx +20 -0
  154. package/src/components/ui/label.tsx +18 -0
  155. package/src/components/ui/popover.tsx +88 -0
  156. package/src/components/ui/scroll-area.tsx +53 -0
  157. package/src/components/ui/select.tsx +192 -0
  158. package/src/components/ui/separator.tsx +23 -0
  159. package/src/components/ui/sheet.tsx +127 -0
  160. package/src/components/ui/sidebar.tsx +723 -0
  161. package/src/components/ui/skeleton.tsx +13 -0
  162. package/src/components/ui/spinner.tsx +10 -0
  163. package/src/components/ui/switch.tsx +32 -0
  164. package/src/components/ui/table.tsx +99 -0
  165. package/src/components/ui/tabs.tsx +82 -0
  166. package/src/components/ui/textarea.tsx +18 -0
  167. package/src/components/ui/tooltip.tsx +70 -0
  168. package/src/config/component-registry.ts +190 -0
  169. package/src/config/index.ts +1099 -0
  170. package/src/hooks/README.md +269 -0
  171. package/src/hooks/admin-provider.tsx +110 -0
  172. package/src/hooks/index.ts +41 -0
  173. package/src/hooks/store.ts +248 -0
  174. package/src/hooks/use-auth.ts +168 -0
  175. package/src/hooks/use-collection-db.ts +209 -0
  176. package/src/hooks/use-collection.ts +156 -0
  177. package/src/hooks/use-global.ts +69 -0
  178. package/src/hooks/use-mobile.ts +21 -0
  179. package/src/lib/utils.ts +6 -0
  180. package/src/styles/index.css +340 -0
  181. package/src/utils/index.ts +6 -0
  182. package/src/views/auth/auth-layout.tsx +77 -0
  183. package/src/views/auth/forgot-password-form.tsx +192 -0
  184. package/src/views/auth/index.ts +21 -0
  185. package/src/views/auth/login-form.tsx +229 -0
  186. package/src/views/auth/reset-password-form.tsx +232 -0
  187. package/src/views/collection/auto-form-fields.tsx +982 -0
  188. package/src/views/collection/collection-form.tsx +186 -0
  189. package/src/views/collection/collection-list.tsx +223 -0
  190. package/src/views/collection/form-field.tsx +52 -0
  191. package/src/views/collection/index.ts +15 -0
  192. package/src/views/common/index.ts +8 -0
  193. package/src/views/common/locale-switcher.tsx +45 -0
  194. package/src/views/common/version-history.tsx +406 -0
  195. package/src/views/index.ts +25 -0
  196. package/src/views/layout/admin-layout.tsx +117 -0
  197. package/src/views/layout/admin-router.tsx +206 -0
  198. package/src/views/layout/admin-sidebar.tsx +185 -0
  199. package/src/views/layout/index.ts +12 -0
  200. package/tsconfig.json +13 -0
  201. package/tsconfig.tsbuildinfo +1 -0
  202. package/tsdown.config.ts +13 -0
  203. package/vitest.config.ts +29 -0
@@ -0,0 +1,148 @@
1
+ import * as React$1 from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { Button } from "../../components/ui/button";
4
+ import { Field, FieldContent, FieldError, FieldGroup, FieldLabel } from "../../components/ui/field";
5
+ import { Input } from "../../components/ui/input";
6
+ import { cn } from "../../lib/utils";
7
+ import { CheckCircle, Envelope, SpinnerGap } from "@phosphor-icons/react";
8
+ import { useForm } from "react-hook-form";
9
+
10
+ //#region src/views/auth/forgot-password-form.tsx
11
+ /**
12
+ * Forgot Password Form - request password reset email
13
+ */
14
+ /**
15
+ * Forgot password form with email field
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * const authClient = createAdminAuthClient<typeof cms>({ baseURL: '...' })
20
+ *
21
+ * function ForgotPasswordPage() {
22
+ * const [error, setError] = useState<string | null>(null)
23
+ *
24
+ * const handleSubmit = async (values: ForgotPasswordFormValues) => {
25
+ * const result = await authClient.forgetPassword({
26
+ * email: values.email,
27
+ * redirectTo: '/reset-password',
28
+ * })
29
+ * if (result.error) {
30
+ * setError(result.error.message)
31
+ * }
32
+ * }
33
+ *
34
+ * return (
35
+ * <AuthLayout title="Forgot password">
36
+ * <ForgotPasswordForm onSubmit={handleSubmit} error={error} />
37
+ * </AuthLayout>
38
+ * )
39
+ * }
40
+ * ```
41
+ */
42
+ function ForgotPasswordForm({ onSubmit, onBackToLoginClick, defaultValues, className, error }) {
43
+ const [isSuccess, setIsSuccess] = React$1.useState(false);
44
+ const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm({ defaultValues: {
45
+ email: "",
46
+ ...defaultValues
47
+ } });
48
+ const handleFormSubmit = handleSubmit(async (values) => {
49
+ await onSubmit(values);
50
+ if (!error) setIsSuccess(true);
51
+ });
52
+ if (isSuccess) return /* @__PURE__ */ jsxs("div", {
53
+ className: cn("space-y-4 text-center", className),
54
+ children: [
55
+ /* @__PURE__ */ jsx("div", {
56
+ className: "bg-primary/10 mx-auto flex size-12 items-center justify-center rounded-full",
57
+ children: /* @__PURE__ */ jsx(CheckCircle, {
58
+ className: "text-primary size-6",
59
+ weight: "duotone"
60
+ })
61
+ }),
62
+ /* @__PURE__ */ jsxs("div", {
63
+ className: "space-y-2",
64
+ children: [/* @__PURE__ */ jsx("h3", {
65
+ className: "text-sm font-medium",
66
+ children: "Check your email"
67
+ }), /* @__PURE__ */ jsx("p", {
68
+ className: "text-muted-foreground text-xs",
69
+ children: "We've sent a password reset link to your email address. Please check your inbox and follow the instructions."
70
+ })]
71
+ }),
72
+ /* @__PURE__ */ jsx(Button, {
73
+ type: "button",
74
+ variant: "outline",
75
+ className: "w-full",
76
+ onClick: onBackToLoginClick,
77
+ children: "Back to login"
78
+ })
79
+ ]
80
+ });
81
+ return /* @__PURE__ */ jsxs("form", {
82
+ onSubmit: handleFormSubmit,
83
+ className: cn("space-y-4", className),
84
+ children: [
85
+ /* @__PURE__ */ jsx("p", {
86
+ className: "text-muted-foreground text-xs",
87
+ children: "Enter your email address and we'll send you a link to reset your password."
88
+ }),
89
+ /* @__PURE__ */ jsx(FieldGroup, { children: /* @__PURE__ */ jsxs(Field, {
90
+ "data-invalid": !!errors.email,
91
+ children: [/* @__PURE__ */ jsx(FieldLabel, {
92
+ htmlFor: "email",
93
+ children: "Email"
94
+ }), /* @__PURE__ */ jsxs(FieldContent, { children: [/* @__PURE__ */ jsxs("div", {
95
+ className: "relative",
96
+ children: [/* @__PURE__ */ jsx(Envelope, {
97
+ className: "text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2",
98
+ weight: "duotone"
99
+ }), /* @__PURE__ */ jsx(Input, {
100
+ id: "email",
101
+ type: "email",
102
+ placeholder: "you@example.com",
103
+ className: "pl-8",
104
+ autoComplete: "email",
105
+ "aria-invalid": !!errors.email,
106
+ ...register("email", {
107
+ required: "Email is required",
108
+ pattern: {
109
+ value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
110
+ message: "Invalid email address"
111
+ }
112
+ })
113
+ })]
114
+ }), /* @__PURE__ */ jsx(FieldError, { children: errors.email?.message })] })]
115
+ }) }),
116
+ error && /* @__PURE__ */ jsx("div", {
117
+ className: "bg-destructive/10 text-destructive rounded-md p-3 text-xs",
118
+ children: error
119
+ }),
120
+ /* @__PURE__ */ jsx(Button, {
121
+ type: "submit",
122
+ className: "w-full",
123
+ size: "lg",
124
+ disabled: isSubmitting,
125
+ children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SpinnerGap, {
126
+ className: "animate-spin",
127
+ weight: "bold"
128
+ }), "Sending..."] }) : "Send reset link"
129
+ }),
130
+ /* @__PURE__ */ jsxs("p", {
131
+ className: "text-muted-foreground text-center text-xs",
132
+ children: [
133
+ "Remember your password?",
134
+ " ",
135
+ /* @__PURE__ */ jsx("button", {
136
+ type: "button",
137
+ onClick: onBackToLoginClick,
138
+ className: "text-primary hover:underline",
139
+ children: "Back to login"
140
+ })
141
+ ]
142
+ })
143
+ ]
144
+ });
145
+ }
146
+
147
+ //#endregion
148
+ export { ForgotPasswordForm };
@@ -0,0 +1,6 @@
1
+ import { AuthLayout } from "./auth-layout";
2
+ import { LoginForm } from "./login-form";
3
+ import { ForgotPasswordForm } from "./forgot-password-form";
4
+ import { ResetPasswordForm } from "./reset-password-form";
5
+
6
+ export { AuthLayout, ForgotPasswordForm, LoginForm, ResetPasswordForm };
@@ -0,0 +1,156 @@
1
+ import "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { Button } from "../../components/ui/button";
4
+ import { Field, FieldContent, FieldError, FieldGroup, FieldLabel } from "../../components/ui/field";
5
+ import { Input } from "../../components/ui/input";
6
+ import { cn } from "../../lib/utils";
7
+ import { Envelope, Lock, SpinnerGap } from "@phosphor-icons/react";
8
+ import { useForm } from "react-hook-form";
9
+
10
+ //#region src/views/auth/login-form.tsx
11
+ /**
12
+ * Login form with email and password fields
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * const authClient = createAdminAuthClient<typeof cms>({ baseURL: '...' })
17
+ *
18
+ * function LoginPage() {
19
+ * const [error, setError] = useState<string | null>(null)
20
+ *
21
+ * const handleLogin = async (values: LoginFormValues) => {
22
+ * const result = await authClient.signIn.email({
23
+ * email: values.email,
24
+ * password: values.password,
25
+ * })
26
+ * if (result.error) {
27
+ * setError(result.error.message)
28
+ * }
29
+ * }
30
+ *
31
+ * return (
32
+ * <AuthLayout title="Sign in">
33
+ * <LoginForm onSubmit={handleLogin} error={error} />
34
+ * </AuthLayout>
35
+ * )
36
+ * }
37
+ * ```
38
+ */
39
+ function LoginForm({ onSubmit, onSignUpClick, onForgotPasswordClick, showRememberMe = false, showSignUp = true, showForgotPassword = true, defaultValues, className, error }) {
40
+ const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm({ defaultValues: {
41
+ email: "",
42
+ password: "",
43
+ rememberMe: false,
44
+ ...defaultValues
45
+ } });
46
+ return /* @__PURE__ */ jsxs("form", {
47
+ onSubmit: handleSubmit(async (values) => {
48
+ await onSubmit(values);
49
+ }),
50
+ className: cn("space-y-4", className),
51
+ children: [
52
+ /* @__PURE__ */ jsxs(FieldGroup, { children: [
53
+ /* @__PURE__ */ jsxs(Field, {
54
+ "data-invalid": !!errors.email,
55
+ children: [/* @__PURE__ */ jsx(FieldLabel, {
56
+ htmlFor: "email",
57
+ children: "Email"
58
+ }), /* @__PURE__ */ jsxs(FieldContent, { children: [/* @__PURE__ */ jsxs("div", {
59
+ className: "relative",
60
+ children: [/* @__PURE__ */ jsx(Envelope, {
61
+ className: "text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2",
62
+ weight: "duotone"
63
+ }), /* @__PURE__ */ jsx(Input, {
64
+ id: "email",
65
+ type: "email",
66
+ placeholder: "you@example.com",
67
+ className: "pl-8",
68
+ autoComplete: "email",
69
+ "aria-invalid": !!errors.email,
70
+ ...register("email", {
71
+ required: "Email is required",
72
+ pattern: {
73
+ value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
74
+ message: "Invalid email address"
75
+ }
76
+ })
77
+ })]
78
+ }), /* @__PURE__ */ jsx(FieldError, { children: errors.email?.message })] })]
79
+ }),
80
+ /* @__PURE__ */ jsxs(Field, {
81
+ "data-invalid": !!errors.password,
82
+ children: [/* @__PURE__ */ jsx(FieldLabel, {
83
+ htmlFor: "password",
84
+ children: "Password"
85
+ }), /* @__PURE__ */ jsxs(FieldContent, { children: [/* @__PURE__ */ jsxs("div", {
86
+ className: "relative",
87
+ children: [/* @__PURE__ */ jsx(Lock, {
88
+ className: "text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2",
89
+ weight: "duotone"
90
+ }), /* @__PURE__ */ jsx(Input, {
91
+ id: "password",
92
+ type: "password",
93
+ placeholder: "Enter your password",
94
+ className: "pl-8",
95
+ autoComplete: "current-password",
96
+ "aria-invalid": !!errors.password,
97
+ ...register("password", {
98
+ required: "Password is required",
99
+ minLength: {
100
+ value: 6,
101
+ message: "Password must be at least 6 characters"
102
+ }
103
+ })
104
+ })]
105
+ }), /* @__PURE__ */ jsx(FieldError, { children: errors.password?.message })] })]
106
+ }),
107
+ (showRememberMe || showForgotPassword) && /* @__PURE__ */ jsxs("div", {
108
+ className: "flex items-center justify-between",
109
+ children: [showRememberMe && /* @__PURE__ */ jsxs("label", {
110
+ className: "text-muted-foreground flex items-center gap-2 text-xs",
111
+ children: [/* @__PURE__ */ jsx("input", {
112
+ type: "checkbox",
113
+ className: "rounded border-gray-300",
114
+ ...register("rememberMe")
115
+ }), "Remember me"]
116
+ }), showForgotPassword && /* @__PURE__ */ jsx("button", {
117
+ type: "button",
118
+ onClick: onForgotPasswordClick,
119
+ className: "text-primary text-xs hover:underline",
120
+ children: "Forgot password?"
121
+ })]
122
+ })
123
+ ] }),
124
+ error && /* @__PURE__ */ jsx("div", {
125
+ className: "bg-destructive/10 text-destructive rounded-md p-3 text-xs",
126
+ children: error
127
+ }),
128
+ /* @__PURE__ */ jsx(Button, {
129
+ type: "submit",
130
+ className: "w-full",
131
+ size: "lg",
132
+ disabled: isSubmitting,
133
+ children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SpinnerGap, {
134
+ className: "animate-spin",
135
+ weight: "bold"
136
+ }), "Signing in..."] }) : "Sign in"
137
+ }),
138
+ showSignUp && /* @__PURE__ */ jsxs("p", {
139
+ className: "text-muted-foreground text-center text-xs",
140
+ children: [
141
+ "Don't have an account?",
142
+ " ",
143
+ /* @__PURE__ */ jsx("button", {
144
+ type: "button",
145
+ onClick: onSignUpClick,
146
+ className: "text-primary hover:underline",
147
+ children: "Sign up"
148
+ })
149
+ ]
150
+ })
151
+ ]
152
+ });
153
+ }
154
+
155
+ //#endregion
156
+ export { LoginForm };
@@ -0,0 +1,184 @@
1
+ import * as React$1 from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { Button } from "../../components/ui/button";
4
+ import { Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel } from "../../components/ui/field";
5
+ import { Input } from "../../components/ui/input";
6
+ import { cn } from "../../lib/utils";
7
+ import { CheckCircle, Lock, SpinnerGap } from "@phosphor-icons/react";
8
+ import { useForm } from "react-hook-form";
9
+
10
+ //#region src/views/auth/reset-password-form.tsx
11
+ /**
12
+ * Reset Password Form - set new password with token
13
+ */
14
+ /**
15
+ * Reset password form with password confirmation
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * const authClient = createAdminAuthClient<typeof cms>({ baseURL: '...' })
20
+ *
21
+ * function ResetPasswordPage() {
22
+ * const token = useSearchParams().get('token')
23
+ * const [error, setError] = useState<string | null>(null)
24
+ *
25
+ * const handleSubmit = async (values) => {
26
+ * const result = await authClient.resetPassword({
27
+ * token: values.token,
28
+ * newPassword: values.password,
29
+ * })
30
+ * if (result.error) {
31
+ * setError(result.error.message)
32
+ * }
33
+ * }
34
+ *
35
+ * return (
36
+ * <AuthLayout title="Reset password">
37
+ * <ResetPasswordForm token={token} onSubmit={handleSubmit} error={error} />
38
+ * </AuthLayout>
39
+ * )
40
+ * }
41
+ * ```
42
+ */
43
+ function ResetPasswordForm({ token, onSubmit, onBackToLoginClick, minPasswordLength = 8, className, error }) {
44
+ const [isSuccess, setIsSuccess] = React$1.useState(false);
45
+ const { register, handleSubmit, watch, formState: { errors, isSubmitting } } = useForm({ defaultValues: {
46
+ password: "",
47
+ confirmPassword: ""
48
+ } });
49
+ const password = watch("password");
50
+ const handleFormSubmit = handleSubmit(async (values) => {
51
+ await onSubmit({
52
+ ...values,
53
+ token
54
+ });
55
+ if (!error) setIsSuccess(true);
56
+ });
57
+ if (isSuccess) return /* @__PURE__ */ jsxs("div", {
58
+ className: cn("space-y-4 text-center", className),
59
+ children: [
60
+ /* @__PURE__ */ jsx("div", {
61
+ className: "bg-primary/10 mx-auto flex size-12 items-center justify-center rounded-full",
62
+ children: /* @__PURE__ */ jsx(CheckCircle, {
63
+ className: "text-primary size-6",
64
+ weight: "duotone"
65
+ })
66
+ }),
67
+ /* @__PURE__ */ jsxs("div", {
68
+ className: "space-y-2",
69
+ children: [/* @__PURE__ */ jsx("h3", {
70
+ className: "text-sm font-medium",
71
+ children: "Password reset successful"
72
+ }), /* @__PURE__ */ jsx("p", {
73
+ className: "text-muted-foreground text-xs",
74
+ children: "Your password has been reset successfully. You can now sign in with your new password."
75
+ })]
76
+ }),
77
+ /* @__PURE__ */ jsx(Button, {
78
+ type: "button",
79
+ className: "w-full",
80
+ size: "lg",
81
+ onClick: onBackToLoginClick,
82
+ children: "Sign in"
83
+ })
84
+ ]
85
+ });
86
+ return /* @__PURE__ */ jsxs("form", {
87
+ onSubmit: handleFormSubmit,
88
+ className: cn("space-y-4", className),
89
+ children: [
90
+ /* @__PURE__ */ jsx("p", {
91
+ className: "text-muted-foreground text-xs",
92
+ children: "Enter your new password below."
93
+ }),
94
+ /* @__PURE__ */ jsxs(FieldGroup, { children: [/* @__PURE__ */ jsxs(Field, {
95
+ "data-invalid": !!errors.password,
96
+ children: [/* @__PURE__ */ jsx(FieldLabel, {
97
+ htmlFor: "password",
98
+ children: "New password"
99
+ }), /* @__PURE__ */ jsxs(FieldContent, { children: [
100
+ /* @__PURE__ */ jsxs("div", {
101
+ className: "relative",
102
+ children: [/* @__PURE__ */ jsx(Lock, {
103
+ className: "text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2",
104
+ weight: "duotone"
105
+ }), /* @__PURE__ */ jsx(Input, {
106
+ id: "password",
107
+ type: "password",
108
+ placeholder: "Enter new password",
109
+ className: "pl-8",
110
+ autoComplete: "new-password",
111
+ "aria-invalid": !!errors.password,
112
+ ...register("password", {
113
+ required: "Password is required",
114
+ minLength: {
115
+ value: minPasswordLength,
116
+ message: `Password must be at least ${minPasswordLength} characters`
117
+ }
118
+ })
119
+ })]
120
+ }),
121
+ /* @__PURE__ */ jsxs(FieldDescription, { children: [
122
+ "Must be at least ",
123
+ minPasswordLength,
124
+ " characters"
125
+ ] }),
126
+ /* @__PURE__ */ jsx(FieldError, { children: errors.password?.message })
127
+ ] })]
128
+ }), /* @__PURE__ */ jsxs(Field, {
129
+ "data-invalid": !!errors.confirmPassword,
130
+ children: [/* @__PURE__ */ jsx(FieldLabel, {
131
+ htmlFor: "confirmPassword",
132
+ children: "Confirm password"
133
+ }), /* @__PURE__ */ jsxs(FieldContent, { children: [/* @__PURE__ */ jsxs("div", {
134
+ className: "relative",
135
+ children: [/* @__PURE__ */ jsx(Lock, {
136
+ className: "text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2",
137
+ weight: "duotone"
138
+ }), /* @__PURE__ */ jsx(Input, {
139
+ id: "confirmPassword",
140
+ type: "password",
141
+ placeholder: "Confirm new password",
142
+ className: "pl-8",
143
+ autoComplete: "new-password",
144
+ "aria-invalid": !!errors.confirmPassword,
145
+ ...register("confirmPassword", {
146
+ required: "Please confirm your password",
147
+ validate: (value) => value === password || "Passwords do not match"
148
+ })
149
+ })]
150
+ }), /* @__PURE__ */ jsx(FieldError, { children: errors.confirmPassword?.message })] })]
151
+ })] }),
152
+ error && /* @__PURE__ */ jsx("div", {
153
+ className: "bg-destructive/10 text-destructive rounded-md p-3 text-xs",
154
+ children: error
155
+ }),
156
+ /* @__PURE__ */ jsx(Button, {
157
+ type: "submit",
158
+ className: "w-full",
159
+ size: "lg",
160
+ disabled: isSubmitting,
161
+ children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SpinnerGap, {
162
+ className: "animate-spin",
163
+ weight: "bold"
164
+ }), "Resetting..."] }) : "Reset password"
165
+ }),
166
+ /* @__PURE__ */ jsxs("p", {
167
+ className: "text-muted-foreground text-center text-xs",
168
+ children: [
169
+ "Remember your password?",
170
+ " ",
171
+ /* @__PURE__ */ jsx("button", {
172
+ type: "button",
173
+ onClick: onBackToLoginClick,
174
+ className: "text-primary hover:underline",
175
+ children: "Back to login"
176
+ })
177
+ ]
178
+ })
179
+ ]
180
+ });
181
+ }
182
+
183
+ //#endregion
184
+ export { ResetPasswordForm };