@better-auth-ui/heroui 1.6.19 → 1.6.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth-ui/heroui",
3
- "version": "1.6.19",
3
+ "version": "1.6.21",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "vite build",
@@ -33,8 +33,8 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@gravity-ui/icons": "^2.18.0",
36
- "@heroui/react": "^3.1.0",
37
- "@heroui/styles": "^3.1.0",
36
+ "@heroui/react": "^3.2.0",
37
+ "@heroui/styles": "^3.2.0",
38
38
  "@internationalized/date": "^3.12.2",
39
39
  "@tanstack/react-pacer": "^0.22.1",
40
40
  "@tanstack/react-query": "^5.100.14",
@@ -42,24 +42,24 @@
42
42
  "@testing-library/user-event": "^14.5.2",
43
43
  "@types/react": "^19.2.15",
44
44
  "@vitejs/plugin-react": "^6.0.2",
45
- "@vitest/browser-playwright": "^4.1.7",
46
- "better-auth": "^1.6.11",
45
+ "@vitest/browser-playwright": "^4.1.9",
46
+ "better-auth": "^1.6.19",
47
47
  "bowser": "^2.11.0",
48
- "playwright": "^1.60.0",
48
+ "playwright": "^1.61.0",
49
49
  "react": "^19.2.6",
50
50
  "react-dom": "^19.2.6",
51
- "vitest": "^4.1.7"
51
+ "vitest": "^4.1.9"
52
52
  },
53
53
  "peerDependencies": {
54
54
  "@better-auth-ui/core": "*",
55
55
  "@better-auth-ui/react": "*",
56
56
  "@gravity-ui/icons": ">=2.18.0",
57
- "@heroui/react": ">=3.1.0",
58
- "@heroui/styles": ">=3.1.0",
57
+ "@heroui/react": ">=3.2.0",
58
+ "@heroui/styles": ">=3.2.0",
59
59
  "@internationalized/date": ">=3.12.2",
60
60
  "@tanstack/react-pacer": ">=0.22.1",
61
61
  "@tanstack/react-query": ">=5.100.14",
62
- "better-auth": ">=1.6.11",
62
+ "better-auth": ">=1.6.19",
63
63
  "react": ">=19.2.6",
64
64
  "react-dom": ">=19.2.6",
65
65
  "bowser": ">=2.11.0"
@@ -258,11 +258,13 @@ export function AdditionalField({
258
258
  isDisabled={isPending}
259
259
  isReadOnly={field.readOnly}
260
260
  >
261
- <Switch.Control>
262
- <Switch.Thumb />
263
- </Switch.Control>
261
+ <Switch.Content>
262
+ <Switch.Control>
263
+ <Switch.Thumb />
264
+ </Switch.Control>
264
265
 
265
- <Label>{field.label}</Label>
266
+ {field.label}
267
+ </Switch.Content>
266
268
  </Switch>
267
269
  )
268
270
  }
@@ -279,12 +281,12 @@ export function AdditionalField({
279
281
  isRequired={field.required}
280
282
  variant={inputVariant}
281
283
  >
282
- <Checkbox.Control>
283
- <Checkbox.Indicator />
284
- </Checkbox.Control>
285
-
286
284
  <Checkbox.Content>
287
- <Label>{field.label}</Label>
285
+ <Checkbox.Control>
286
+ <Checkbox.Indicator />
287
+ </Checkbox.Control>
288
+
289
+ {field.label}
288
290
  </Checkbox.Content>
289
291
  </Checkbox>
290
292
  )
@@ -37,6 +37,7 @@ const AUTH_VIEWS: Partial<Record<AuthView, ComponentType<AuthProps>>> = {
37
37
  /**
38
38
  * Render the appropriate authentication view based on the provided `view` or `path`.
39
39
  *
40
+ * @param className - Class name applied to the rendered view's card
40
41
  * @param path - Route path used to resolve an auth view when `view` is not provided
41
42
  * @param socialLayout - Social layout to apply to sign-in/sign-up/magic-link views
42
43
  * @param socialPosition - Position for social buttons ("top" or "bottom")
@@ -45,12 +46,13 @@ const AUTH_VIEWS: Partial<Record<AuthView, ComponentType<AuthProps>>> = {
45
46
  * @returns The React element for the resolved authentication view
46
47
  */
47
48
  export function Auth({
49
+ className,
48
50
  path,
49
51
  socialLayout,
50
52
  socialPosition,
51
- view,
52
- ...props
53
- }: AuthProps & Omit<CardProps, "children">) {
53
+ variant,
54
+ view
55
+ }: AuthProps) {
54
56
  const { basePaths, emailAndPassword, plugins, viewPaths, navigate } =
55
57
  useAuth()
56
58
 
@@ -107,9 +109,10 @@ export function Auth({
107
109
 
108
110
  return (
109
111
  <PluginView
112
+ className={className}
110
113
  socialLayout={socialLayout}
111
114
  socialPosition={socialPosition}
112
- {...props}
115
+ variant={variant}
113
116
  />
114
117
  )
115
118
  }
@@ -125,9 +128,10 @@ export function Auth({
125
128
  if (Fallback) {
126
129
  return (
127
130
  <Fallback
131
+ className={className}
128
132
  socialLayout={socialLayout}
129
133
  socialPosition={socialPosition}
130
- {...props}
134
+ variant={variant}
131
135
  />
132
136
  )
133
137
  }
@@ -143,9 +147,10 @@ export function Auth({
143
147
 
144
148
  return (
145
149
  <AuthView
150
+ className={className}
146
151
  socialLayout={socialLayout}
147
152
  socialPosition={socialPosition}
148
- {...props}
153
+ variant={variant}
149
154
  />
150
155
  )
151
156
  }
@@ -34,11 +34,7 @@ export type ForgotPasswordProps = {
34
34
  * @param className - Optional additional CSS class names applied to the card
35
35
  * @returns The forgot-password form UI as a JSX element
36
36
  */
37
- export function ForgotPassword({
38
- className,
39
- variant,
40
- ...props
41
- }: ForgotPasswordProps & Omit<CardProps, "children">) {
37
+ export function ForgotPassword({ className, variant }: ForgotPasswordProps) {
42
38
  const {
43
39
  authClient,
44
40
  baseURL,
@@ -83,7 +79,6 @@ export function ForgotPassword({
83
79
  <Card
84
80
  className={cn("w-full max-w-sm gap-4 md:p-6", className)}
85
81
  variant={variant}
86
- {...props}
87
82
  >
88
83
  <Card.Header>
89
84
  <Card.Title className="text-xl font-semibold mb-1">
@@ -45,9 +45,8 @@ export function MagicLink({
45
45
  className,
46
46
  socialLayout,
47
47
  socialPosition = "bottom",
48
- variant,
49
- ...props
50
- }: MagicLinkProps & Omit<CardProps, "children">) {
48
+ variant
49
+ }: MagicLinkProps) {
51
50
  const {
52
51
  authClient,
53
52
  basePaths,
@@ -90,7 +89,6 @@ export function MagicLink({
90
89
  <Card
91
90
  className={cn("w-full max-w-sm gap-4 md:p-6", className)}
92
91
  variant={variant}
93
- {...props}
94
92
  >
95
93
  <Card.Header>
96
94
  <Card.Title className="text-xl font-semibold mb-1">
@@ -6,7 +6,7 @@ import {
6
6
  useHasPermission,
7
7
  useListOrganizationInvitations
8
8
  } from "@better-auth-ui/react"
9
- import { ChevronUp, Funnel, Xmark } from "@gravity-ui/icons"
9
+ import { Funnel, Xmark } from "@gravity-ui/icons"
10
10
  import {
11
11
  Button,
12
12
  Chip,
@@ -17,7 +17,7 @@ import {
17
17
  type SortDescriptor,
18
18
  Table
19
19
  } from "@heroui/react"
20
- import { type ComponentProps, type ReactNode, useMemo, useState } from "react"
20
+ import { type ComponentProps, useMemo, useState } from "react"
21
21
 
22
22
  import { organizationPlugin } from "../../../lib/auth/organization-plugin"
23
23
  import { InviteMemberDialog } from "./invite-member-dialog"
@@ -264,33 +264,33 @@ export function OrganizationInvitations({
264
264
  <Table.Header>
265
265
  <Table.Column allowsSorting isRowHeader id="email">
266
266
  {({ sortDirection }) => (
267
- <SortableColumnHeader sortDirection={sortDirection}>
267
+ <Table.SortableColumnHeader sortDirection={sortDirection}>
268
268
  {localization.auth.email}
269
- </SortableColumnHeader>
269
+ </Table.SortableColumnHeader>
270
270
  )}
271
271
  </Table.Column>
272
272
 
273
273
  <Table.Column allowsSorting id="createdAt">
274
274
  {({ sortDirection }) => (
275
- <SortableColumnHeader sortDirection={sortDirection}>
275
+ <Table.SortableColumnHeader sortDirection={sortDirection}>
276
276
  {organizationLocalization.invitedAt}
277
- </SortableColumnHeader>
277
+ </Table.SortableColumnHeader>
278
278
  )}
279
279
  </Table.Column>
280
280
 
281
281
  <Table.Column allowsSorting id="role">
282
282
  {({ sortDirection }) => (
283
- <SortableColumnHeader sortDirection={sortDirection}>
283
+ <Table.SortableColumnHeader sortDirection={sortDirection}>
284
284
  {organizationLocalization.role}
285
- </SortableColumnHeader>
285
+ </Table.SortableColumnHeader>
286
286
  )}
287
287
  </Table.Column>
288
288
 
289
289
  <Table.Column allowsSorting id="status">
290
290
  {({ sortDirection }) => (
291
- <SortableColumnHeader sortDirection={sortDirection}>
291
+ <Table.SortableColumnHeader sortDirection={sortDirection}>
292
292
  {organizationLocalization.status}
293
- </SortableColumnHeader>
293
+ </Table.SortableColumnHeader>
294
294
  )}
295
295
  </Table.Column>
296
296
 
@@ -326,26 +326,3 @@ export function OrganizationInvitations({
326
326
  </div>
327
327
  )
328
328
  }
329
-
330
- function SortableColumnHeader({
331
- children,
332
- sortDirection
333
- }: {
334
- children: ReactNode
335
- sortDirection?: "ascending" | "descending"
336
- }) {
337
- return (
338
- <span className="flex items-center justify-between">
339
- {children}
340
-
341
- {!!sortDirection && (
342
- <ChevronUp
343
- className={cn(
344
- "size-3 transform transition-transform duration-100 ease-out",
345
- sortDirection === "descending" ? "rotate-180" : ""
346
- )}
347
- />
348
- )}
349
- </span>
350
- )
351
- }
@@ -7,7 +7,7 @@ import {
7
7
  useListOrganizationMembers,
8
8
  useSession
9
9
  } from "@better-auth-ui/react"
10
- import { ChevronUp, Funnel, Xmark } from "@gravity-ui/icons"
10
+ import { Funnel, Xmark } from "@gravity-ui/icons"
11
11
  import {
12
12
  Button,
13
13
  Chip,
@@ -19,7 +19,7 @@ import {
19
19
  Table
20
20
  } from "@heroui/react"
21
21
  import type { Member } from "better-auth/client"
22
- import { type ComponentProps, type ReactNode, useMemo, useState } from "react"
22
+ import { type ComponentProps, useMemo, useState } from "react"
23
23
 
24
24
  import { organizationPlugin } from "../../../lib/auth/organization-plugin"
25
25
  import { InviteMemberDialog } from "./invite-member-dialog"
@@ -216,17 +216,17 @@ export function OrganizationMembers({
216
216
  <Table.Header>
217
217
  <Table.Column allowsSorting isRowHeader id="user">
218
218
  {({ sortDirection }) => (
219
- <SortableColumnHeader sortDirection={sortDirection}>
219
+ <Table.SortableColumnHeader sortDirection={sortDirection}>
220
220
  {organizationLocalization.member}
221
- </SortableColumnHeader>
221
+ </Table.SortableColumnHeader>
222
222
  )}
223
223
  </Table.Column>
224
224
 
225
225
  <Table.Column allowsSorting id="role">
226
226
  {({ sortDirection }) => (
227
- <SortableColumnHeader sortDirection={sortDirection}>
227
+ <Table.SortableColumnHeader sortDirection={sortDirection}>
228
228
  {organizationLocalization.role}
229
- </SortableColumnHeader>
229
+ </Table.SortableColumnHeader>
230
230
  )}
231
231
  </Table.Column>
232
232
 
@@ -259,26 +259,3 @@ export function OrganizationMembers({
259
259
  </div>
260
260
  )
261
261
  }
262
-
263
- function SortableColumnHeader({
264
- children,
265
- sortDirection
266
- }: {
267
- children: ReactNode
268
- sortDirection?: "ascending" | "descending"
269
- }) {
270
- return (
271
- <span className="flex items-center justify-between">
272
- {children}
273
-
274
- {!!sortDirection && (
275
- <ChevronUp
276
- className={cn(
277
- "size-3 transform transition-transform duration-100 ease-out",
278
- sortDirection === "descending" ? "rotate-180" : ""
279
- )}
280
- />
281
- )}
282
- </span>
283
- )
284
- }
@@ -27,11 +27,7 @@ export type ResetPasswordProps = {
27
27
  *
28
28
  * Renders password (and optional confirm-password) inputs with visibility toggles, applies min/max length constraints from the auth configuration, shows field errors, and submits the new password to the auth client.
29
29
  */
30
- export function ResetPassword({
31
- className,
32
- variant,
33
- ...props
34
- }: ResetPasswordProps & Omit<CardProps, "children">) {
30
+ export function ResetPassword({ className, variant }: ResetPasswordProps) {
35
31
  const {
36
32
  authClient,
37
33
  basePaths,
@@ -95,7 +91,6 @@ export function ResetPassword({
95
91
  <Card
96
92
  className={cn("w-full max-w-sm gap-4 md:p-6", className)}
97
93
  variant={variant}
98
- {...props}
99
94
  >
100
95
  <Card.Header>
101
96
  <Card.Title className="text-xl font-semibold mb-1">
@@ -43,9 +43,8 @@ export function SignIn({
43
43
  className,
44
44
  socialLayout,
45
45
  socialPosition = "bottom",
46
- variant,
47
- ...props
48
- }: SignInProps & Omit<CardProps, "children">) {
46
+ variant
47
+ }: SignInProps) {
49
48
  const {
50
49
  authClient,
51
50
  basePaths,
@@ -128,7 +127,6 @@ export function SignIn({
128
127
  <Card
129
128
  className={cn("w-full max-w-sm gap-4 md:p-6", className)}
130
129
  variant={variant}
131
- {...props}
132
130
  >
133
131
  <Card.Header>
134
132
  <Card.Title className="text-xl font-semibold mb-1">
@@ -215,12 +213,12 @@ export function SignIn({
215
213
  isDisabled={isPending}
216
214
  variant={variant === "transparent" ? "primary" : "secondary"}
217
215
  >
218
- <Checkbox.Control>
219
- <Checkbox.Indicator />
220
- </Checkbox.Control>
221
-
222
216
  <Checkbox.Content>
223
- <Label>{localization.auth.rememberMe}</Label>
217
+ <Checkbox.Control>
218
+ <Checkbox.Indicator />
219
+ </Checkbox.Control>
220
+
221
+ {localization.auth.rememberMe}
224
222
  </Checkbox.Content>
225
223
  </Checkbox>
226
224
  )}
@@ -263,7 +261,7 @@ export function SignIn({
263
261
  {emailAndPassword?.enabled && emailAndPassword?.forgotPassword && (
264
262
  <Link
265
263
  href={`${basePaths.auth}/${viewPaths.auth.forgotPassword}`}
266
- className="no-underline hover:underline"
264
+ className="text-sm no-underline hover:underline"
267
265
  >
268
266
  {localization.auth.forgotPasswordLink}
269
267
  </Link>
@@ -47,9 +47,8 @@ export function SignUp({
47
47
  className,
48
48
  socialLayout,
49
49
  socialPosition = "bottom",
50
- variant,
51
- ...props
52
- }: SignUpProps & Omit<CardProps, "children">) {
50
+ variant
51
+ }: SignUpProps) {
53
52
  const {
54
53
  additionalFields,
55
54
  authClient,
@@ -156,7 +155,6 @@ export function SignUp({
156
155
  <Card
157
156
  className={cn("w-full max-w-sm gap-4 md:p-6", className)}
158
157
  variant={variant}
159
- {...props}
160
158
  >
161
159
  <Card.Header>
162
160
  <Card.Title className="text-xl font-semibold mb-1">
@@ -69,10 +69,10 @@ export function Appearance({
69
69
  >
70
70
  <Radio.Content className="gap-2">
71
71
  <div className="flex gap-2 justify-between">
72
- <Label className="flex gap-2 items-center">
72
+ <span className="flex gap-2 items-center">
73
73
  <Display className="text-muted" />
74
74
  {localization.system}
75
- </Label>
75
+ </span>
76
76
 
77
77
  <Radio.Control>
78
78
  <Radio.Indicator />
@@ -98,10 +98,10 @@ export function Appearance({
98
98
  >
99
99
  <Radio.Content className="gap-2">
100
100
  <div className="flex gap-2 justify-between">
101
- <Label className="flex gap-2 items-center">
101
+ <span className="flex gap-2 items-center">
102
102
  <Sun className="text-muted" />
103
103
  {localization.light}
104
- </Label>
104
+ </span>
105
105
 
106
106
  <Radio.Control>
107
107
  <Radio.Indicator />
@@ -127,10 +127,10 @@ export function Appearance({
127
127
  >
128
128
  <Radio.Content className="gap-2">
129
129
  <div className="flex gap-2 justify-between">
130
- <Label className="flex gap-2 items-center">
130
+ <span className="flex gap-2 items-center">
131
131
  <Moon className="text-muted" />
132
132
  {localization.dark}
133
- </Label>
133
+ </span>
134
134
 
135
135
  <Radio.Control>
136
136
  <Radio.Indicator />
@@ -123,8 +123,8 @@ export function UserButton({
123
123
  return (
124
124
  <Dropdown>
125
125
  {size === "icon" ? (
126
- <Dropdown.Trigger className={cn("rounded-full", className)}>
127
- <UserAvatar />
126
+ <Dropdown.Trigger className={cn("rounded-full")}>
127
+ <UserAvatar className={className} />
128
128
  </Dropdown.Trigger>
129
129
  ) : (
130
130
  <Button
@@ -46,9 +46,8 @@ export function SignInUsername({
46
46
  className,
47
47
  socialLayout,
48
48
  socialPosition = "bottom",
49
- variant,
50
- ...props
51
- }: SignInUsernameProps & Omit<CardProps, "children">) {
49
+ variant
50
+ }: SignInUsernameProps) {
52
51
  const {
53
52
  authClient,
54
53
  basePaths,
@@ -154,7 +153,6 @@ export function SignInUsername({
154
153
  <Card
155
154
  className={cn("w-full max-w-sm gap-4 md:p-6", className)}
156
155
  variant={variant}
157
- {...props}
158
156
  >
159
157
  <Card.Header>
160
158
  <Card.Title className="text-xl font-semibold mb-1">
@@ -239,12 +237,12 @@ export function SignInUsername({
239
237
  isDisabled={isPending}
240
238
  variant={variant === "transparent" ? "primary" : "secondary"}
241
239
  >
242
- <Checkbox.Control>
243
- <Checkbox.Indicator />
244
- </Checkbox.Control>
245
-
246
240
  <Checkbox.Content>
247
- <Label>{localization.auth.rememberMe}</Label>
241
+ <Checkbox.Control>
242
+ <Checkbox.Indicator />
243
+ </Checkbox.Control>
244
+
245
+ {localization.auth.rememberMe}
248
246
  </Checkbox.Content>
249
247
  </Checkbox>
250
248
  )}
@@ -291,7 +289,7 @@ export function SignInUsername({
291
289
  {emailAndPassword?.enabled && emailAndPassword?.forgotPassword && (
292
290
  <Link
293
291
  href={`${basePaths.auth}/${viewPaths.auth.forgotPassword}`}
294
- className="no-underline hover:underline"
292
+ className="text-sm no-underline hover:underline"
295
293
  >
296
294
  {localization.auth.forgotPasswordLink}
297
295
  </Link>
@@ -55,10 +55,12 @@ export type AuthPluginComponents = Omit<
55
55
  userMenuItems?: ComponentType<UserMenuItemProps>[]
56
56
  }
57
57
 
58
- /** Props the heroui `<Auth>` router spreads onto plugin-contributed auth views. */
59
- export type AuthViewProps = Omit<CardProps, "children"> & {
58
+ /** Props the heroui `<Auth>` router passes to plugin-contributed auth views. */
59
+ export type AuthViewProps = {
60
+ className?: string
60
61
  socialLayout?: SocialLayout
61
62
  socialPosition?: "top" | "bottom"
63
+ variant?: CardProps["variant"]
62
64
  }
63
65
 
64
66
  /** Props the heroui `<Settings>` router spreads onto plugin-contributed settings views. */