betterstart-cli 0.0.106 → 0.0.107

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 (99) hide show
  1. package/dist/assets/adapters/next/templates/init/components/layouts/admin-nav-link.tsx +10 -8
  2. package/dist/assets/adapters/next/templates/init/components/layouts/admin-sidebar-nav-link-skeleton.tsx +1 -5
  3. package/dist/assets/adapters/next/templates/init/components/layouts/admin-sidebar-user-menu.tsx +54 -48
  4. package/dist/assets/adapters/next/templates/init/components/layouts/admin-sign-out.tsx +2 -2
  5. package/dist/assets/adapters/next/templates/init/components/shared/delete-dialog.tsx +3 -5
  6. package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/lifecycle-hooks-tab.tsx +1 -1
  7. package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/snippets-tab.tsx +1 -1
  8. package/dist/assets/adapters/next/templates/init/components/shared/dev-mode-integrate.tsx +5 -7
  9. package/dist/assets/adapters/next/templates/init/components/shared/entity-filters-bar.tsx +9 -10
  10. package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-version-item.tsx +2 -4
  11. package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-version-restore-dialog.tsx +2 -4
  12. package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-versions-current-row.tsx +2 -4
  13. package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-versions-drawer.tsx +1 -1
  14. package/dist/assets/adapters/next/templates/init/components/shared/media/edit-media-dialog.tsx +2 -2
  15. package/dist/assets/adapters/next/templates/init/components/shared/media/media-delete-dialog.tsx +5 -5
  16. package/dist/assets/adapters/next/templates/init/components/shared/media/media-delete-drawer.tsx +52 -53
  17. package/dist/assets/adapters/next/templates/init/components/shared/sort-order-dialog.tsx +3 -5
  18. package/dist/assets/adapters/next/templates/init/pages/dashboard-page.tsx +1 -1
  19. package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-detail-drawer.tsx +1 -1
  20. package/dist/assets/adapters/next/templates/init/pages/settings/forms/form-notifications-drawer.tsx +5 -5
  21. package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhook-actions.tsx +20 -20
  22. package/dist/assets/adapters/next/templates/init/pages/users/change-password-dialog.tsx +7 -5
  23. package/dist/assets/adapters/next/templates/init/pages/users/columns.tsx +3 -5
  24. package/dist/assets/adapters/next/templates/init/pages/users/create-user-dialog.tsx +1 -3
  25. package/dist/assets/adapters/next/templates/init/pages/users/delete-user-dialog.tsx +11 -5
  26. package/dist/assets/adapters/next/templates/init/pages/users/edit-role-dialog.tsx +1 -1
  27. package/dist/assets/shared-assets/react-admin/custom/content-editor/math-popover-button.tsx +13 -11
  28. package/dist/assets/shared-assets/react-admin/custom/content-editor/source-mode-dropdown-button.tsx +16 -14
  29. package/dist/assets/shared-assets/react-admin/custom/content-editor/source-mode.tsx +2 -2
  30. package/dist/assets/shared-assets/react-admin/custom/content-editor/table-button.tsx +14 -12
  31. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/color-highlight-popover/color-highlight-popover.tsx +16 -14
  32. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/color-highlight-popover/source-color-highlight-popover.tsx +15 -13
  33. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu-item.tsx +1 -1
  34. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu.tsx +31 -29
  35. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/link-popover/link-control-popover.tsx +15 -13
  36. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/list-dropdown-menu/list-dropdown-menu-item.tsx +1 -1
  37. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/list-dropdown-menu/list-dropdown-menu.tsx +22 -20
  38. package/dist/assets/shared-assets/react-admin/custom/date-picker.tsx +16 -14
  39. package/dist/assets/shared-assets/react-admin/custom/date-range-picker.tsx +8 -6
  40. package/dist/assets/shared-assets/react-admin/custom/icon-picker.tsx +8 -7
  41. package/dist/assets/shared-assets/react-admin/custom/nested-object-list-field.tsx +2 -4
  42. package/dist/assets/shared-assets/react-admin/ui/accordion.tsx +11 -28
  43. package/dist/assets/shared-assets/react-admin/ui/alert-dialog.tsx +30 -47
  44. package/dist/assets/shared-assets/react-admin/ui/alert.tsx +4 -4
  45. package/dist/assets/shared-assets/react-admin/ui/aspect-ratio.tsx +18 -5
  46. package/dist/assets/shared-assets/react-admin/ui/avatar.tsx +10 -13
  47. package/dist/assets/shared-assets/react-admin/ui/badge.tsx +21 -20
  48. package/dist/assets/shared-assets/react-admin/ui/breadcrumb.tsx +20 -19
  49. package/dist/assets/shared-assets/react-admin/ui/button-group.tsx +25 -24
  50. package/dist/assets/shared-assets/react-admin/ui/button.tsx +22 -31
  51. package/dist/assets/shared-assets/react-admin/ui/calendar.tsx +9 -6
  52. package/dist/assets/shared-assets/react-admin/ui/card.tsx +6 -16
  53. package/dist/assets/shared-assets/react-admin/ui/carousel.tsx +20 -17
  54. package/dist/assets/shared-assets/react-admin/ui/chart.tsx +19 -16
  55. package/dist/assets/shared-assets/react-admin/ui/checkbox.tsx +3 -4
  56. package/dist/assets/shared-assets/react-admin/ui/collapsible.tsx +6 -10
  57. package/dist/assets/shared-assets/react-admin/ui/combobox.tsx +10 -36
  58. package/dist/assets/shared-assets/react-admin/ui/command.tsx +7 -6
  59. package/dist/assets/shared-assets/react-admin/ui/context-menu.tsx +77 -79
  60. package/dist/assets/shared-assets/react-admin/ui/dialog.tsx +29 -54
  61. package/dist/assets/shared-assets/react-admin/ui/direction.tsx +1 -18
  62. package/dist/assets/shared-assets/react-admin/ui/drawer.tsx +121 -49
  63. package/dist/assets/shared-assets/react-admin/ui/dropdown-menu.tsx +117 -131
  64. package/dist/assets/shared-assets/react-admin/ui/empty.tsx +3 -3
  65. package/dist/assets/shared-assets/react-admin/ui/field.tsx +20 -30
  66. package/dist/assets/shared-assets/react-admin/ui/form.tsx +27 -31
  67. package/dist/assets/shared-assets/react-admin/ui/hover-card.tsx +26 -18
  68. package/dist/assets/shared-assets/react-admin/ui/input-group.tsx +25 -12
  69. package/dist/assets/shared-assets/react-admin/ui/input-otp.tsx +3 -3
  70. package/dist/assets/shared-assets/react-admin/ui/input.tsx +4 -3
  71. package/dist/assets/shared-assets/react-admin/ui/item.tsx +26 -19
  72. package/dist/assets/shared-assets/react-admin/ui/label.tsx +18 -14
  73. package/dist/assets/shared-assets/react-admin/ui/menubar.tsx +80 -73
  74. package/dist/assets/shared-assets/react-admin/ui/native-select.tsx +3 -3
  75. package/dist/assets/shared-assets/react-admin/ui/navigation-menu.tsx +40 -39
  76. package/dist/assets/shared-assets/react-admin/ui/pagination.tsx +18 -11
  77. package/dist/assets/shared-assets/react-admin/ui/popover.tsx +31 -30
  78. package/dist/assets/shared-assets/react-admin/ui/progress.tsx +51 -16
  79. package/dist/assets/shared-assets/react-admin/ui/radio-group.tsx +11 -17
  80. package/dist/assets/shared-assets/react-admin/ui/resizable.tsx +1 -1
  81. package/dist/assets/shared-assets/react-admin/ui/scroll-area.tsx +9 -13
  82. package/dist/assets/shared-assets/react-admin/ui/select.tsx +66 -60
  83. package/dist/assets/shared-assets/react-admin/ui/separator.tsx +3 -10
  84. package/dist/assets/shared-assets/react-admin/ui/sheet.tsx +22 -27
  85. package/dist/assets/shared-assets/react-admin/ui/sidebar.tsx +144 -126
  86. package/dist/assets/shared-assets/react-admin/ui/skeleton.tsx +1 -1
  87. package/dist/assets/shared-assets/react-admin/ui/slider.tsx +27 -29
  88. package/dist/assets/shared-assets/react-admin/ui/sonner.tsx +8 -3
  89. package/dist/assets/shared-assets/react-admin/ui/spinner.tsx +4 -3
  90. package/dist/assets/shared-assets/react-admin/ui/switch.tsx +4 -5
  91. package/dist/assets/shared-assets/react-admin/ui/table.tsx +8 -21
  92. package/dist/assets/shared-assets/react-admin/ui/tabs.tsx +11 -16
  93. package/dist/assets/shared-assets/react-admin/ui/textarea.tsx +2 -2
  94. package/dist/assets/shared-assets/react-admin/ui/toggle-group.tsx +12 -11
  95. package/dist/assets/shared-assets/react-admin/ui/toggle.tsx +4 -5
  96. package/dist/assets/shared-assets/react-admin/ui/tooltip.tsx +29 -27
  97. package/dist/cli.js +90 -110
  98. package/dist/cli.js.map +1 -1
  99. package/package.json +1 -1
@@ -20,14 +20,16 @@ export function AdminNavLink({
20
20
  : pathname === href || pathname.startsWith(`${href}/`)
21
21
 
22
22
  return (
23
- <SidebarMenuButton asChild>
24
- <Link
25
- aria-current={isActive ? 'page' : undefined}
26
- data-active={isActive ? true : undefined}
27
- href={href}
28
- >
29
- {children}
30
- </Link>
23
+ <SidebarMenuButton
24
+ render={
25
+ <Link
26
+ aria-current={isActive ? 'page' : undefined}
27
+ data-active={isActive ? true : undefined}
28
+ href={href}
29
+ />
30
+ }
31
+ >
32
+ {children}
31
33
  </SidebarMenuButton>
32
34
  )
33
35
  }
@@ -3,9 +3,5 @@ import { SidebarMenuButton } from '@admin/components/ui/sidebar'
3
3
  import Link from 'next/link'
4
4
 
5
5
  export function SidebarNavLinkSkeleton({ href, children }: { href: string; children: ReactNode }) {
6
- return (
7
- <SidebarMenuButton asChild>
8
- <Link href={href}>{children}</Link>
9
- </SidebarMenuButton>
10
- )
6
+ return <SidebarMenuButton render={<Link href={href} />}>{children}</SidebarMenuButton>
11
7
  }
@@ -24,61 +24,67 @@ export async function SidebarUserMenu() {
24
24
  <SidebarMenu className="h-full">
25
25
  <SidebarMenuItem className="h-full">
26
26
  <DropdownMenu>
27
- <DropdownMenuTrigger asChild>
28
- <Button
29
- variant="ghost"
30
- className="h-full w-full justify-start border-none bg-transparent! px-3 text-left ring-0!"
31
- >
32
- <Avatar className="size-8 shrink-0">
33
- <AvatarImage src={user.image ?? undefined} />
34
- <AvatarFallback className="text-xs font-semibold group-hover:bg-white">
35
- {user.name?.charAt(0) ?? user.email?.charAt(0) ?? '?'}
36
- </AvatarFallback>
37
- </Avatar>
38
- <div className="flex-1 truncate group-data-[collapsible=icon]:hidden">
39
- <p className="truncate font-medium">{user.name}</p>
40
- </div>
27
+ <DropdownMenuTrigger
28
+ render={
29
+ <Button
30
+ variant="ghost"
31
+ className="h-full w-full justify-start border-none bg-transparent! px-3 text-left ring-0!"
32
+ >
33
+ <Avatar className="size-8 shrink-0">
34
+ <AvatarImage src={user.image ?? undefined} />
35
+ <AvatarFallback className="text-xs font-semibold group-hover:bg-white">
36
+ {user.name?.charAt(0) ?? user.email?.charAt(0) ?? '?'}
37
+ </AvatarFallback>
38
+ </Avatar>
39
+ <div className="flex-1 truncate group-data-[collapsible=icon]:hidden">
40
+ <p className="truncate font-medium">{user.name}</p>
41
+ </div>
41
42
 
42
- <div className="group-data-[collapsible=icon]:hidden">
43
- <span
44
- className={cn(
45
- buttonVariants({ variant: 'outline', size: 'icon' }),
46
- 'size-7 rounded-sm group-hover:bg-white'
47
- )}
48
- >
49
- <Ellipsis strokeWidth={2} className="size-4" />
50
- </span>
51
- </div>
52
- </Button>
53
- </DropdownMenuTrigger>
43
+ <div className="group-data-[collapsible=icon]:hidden">
44
+ <span
45
+ className={cn(
46
+ buttonVariants({ variant: 'outline', size: 'icon' }),
47
+ 'size-7 rounded-sm group-hover:bg-white'
48
+ )}
49
+ >
50
+ <Ellipsis strokeWidth={2} className="size-4" />
51
+ </span>
52
+ </div>
53
+ </Button>
54
+ }
55
+ />
54
56
  <DropdownMenuContent align="start" alignOffset={12} className="w-68 p-1">
55
57
  <DropdownMenuGroup>
56
- <DropdownMenuItem className="justify-between" asChild>
57
- <Link
58
- href="/admin/profile"
59
- prefetch={true}
60
- className="flex w-full items-center justify-between gap-2 py-2 pr-1"
61
- >
62
- <div className="flex items-center gap-2">
63
- <div className="flex flex-col">
64
- <p className="truncate font-medium">{user.name}</p>
65
- <p className="truncate text-sm font-normal text-muted-foreground [text-box-trim:trim-start]">
66
- {user.email}
67
- </p>
68
- </div>
58
+ <DropdownMenuItem
59
+ className="justify-between"
60
+ render={
61
+ <Link
62
+ href="/admin/profile"
63
+ prefetch={true}
64
+ className="flex w-full items-center justify-between gap-2 py-2 pr-1"
65
+ />
66
+ }
67
+ >
68
+ <div className="flex items-center gap-2">
69
+ <div className="flex flex-col">
70
+ <p className="truncate font-medium">{user.name}</p>
71
+ <p className="truncate text-sm font-normal text-muted-foreground [text-box-trim:trim-start]">
72
+ {user.email}
73
+ </p>
69
74
  </div>
70
- <Button variant="ghost" className="pointer-events-none size-8! shrink-0">
71
- <Settings strokeWidth={2} className="size-4" />
72
- </Button>
73
- </Link>
75
+ </div>
76
+ <Button variant="ghost" className="pointer-events-none size-8! shrink-0">
77
+ <Settings strokeWidth={2} className="size-4" />
78
+ </Button>
74
79
  </DropdownMenuItem>
75
80
  </DropdownMenuGroup>
76
81
  <DropdownMenuGroup>
77
- <DropdownMenuItem className="justify-between" asChild>
78
- <Link href="https://betterstart.io/docs" target="_blank">
79
- <span>Docs</span>
80
- <BookOpen strokeWidth={1.2} className="size-4" />
81
- </Link>
82
+ <DropdownMenuItem
83
+ className="justify-between"
84
+ render={<Link href="https://betterstart.io/docs" target="_blank" />}
85
+ >
86
+ <span>Docs</span>
87
+ <BookOpen strokeWidth={1.2} className="size-4" />
82
88
  </DropdownMenuItem>
83
89
  <AdminSignOut className="justify-between" />
84
90
  </DropdownMenuGroup>
@@ -48,8 +48,8 @@ export function AdminSignOut({
48
48
 
49
49
  return (
50
50
  <DropdownMenuItem
51
- onSelect={(event) => {
52
- event.preventDefault()
51
+ closeOnClick={false}
52
+ onClick={() => {
53
53
  handleSignOut()
54
54
  }}
55
55
  disabled={isPending}
@@ -34,11 +34,9 @@ export function DeleteDialog({
34
34
 
35
35
  return (
36
36
  <AlertDialog open={open} onOpenChange={setOpen}>
37
- <AlertDialogTrigger asChild>
38
- <Button variant="destructive" size="default">
39
- <Trash2 className="-ml-0.5 size-3.5" strokeWidth={2} />
40
- Delete {count} {label}
41
- </Button>
37
+ <AlertDialogTrigger render={<Button variant="destructive" size="default" />}>
38
+ <Trash2 className="-ml-0.5 size-3.5" strokeWidth={2} />
39
+ Delete {count} {label}
42
40
  </AlertDialogTrigger>
43
41
  <AlertDialogContent>
44
42
  <AlertDialogHeader>
@@ -50,7 +50,7 @@ export function LifecycleHooksTab({ lifecycleHooks }: LifecycleHooksTabProps) {
50
50
  }
51
51
 
52
52
  return (
53
- <Accordion type="single" defaultValue={firstHook.id} className="min-h-0 shrink-0 rounded-sm">
53
+ <Accordion defaultValue={[firstHook.id]} className="min-h-0 shrink-0 rounded-sm">
54
54
  {lifecycleHooks.map((hook) => {
55
55
  const HookIcon = LIFECYCLE_HOOK_ICONS[hook.icon]
56
56
  const phaseLabel = LIFECYCLE_HOOK_PHASE_LABELS[hook.phase]
@@ -47,7 +47,7 @@ export function SnippetsTab({ snippets }: SnippetsTabProps) {
47
47
  }
48
48
 
49
49
  return (
50
- <Accordion type="single" defaultValue={firstSnippet.id} className="min-h-0 shrink-0 rounded-sm">
50
+ <Accordion defaultValue={[firstSnippet.id]} className="min-h-0 shrink-0 rounded-sm">
51
51
  {snippets.map((snippet) => {
52
52
  const SnippetIcon = SNIPPET_ICONS[snippet.icon]
53
53
  const snippetKindLabel = SNIPPET_KIND_LABELS[snippet.kind]
@@ -46,14 +46,12 @@ export function DevModeIntegrateButton({
46
46
  }
47
47
 
48
48
  return (
49
- <Drawer direction="right" handleOnly onOpenChange={handleOpenChange}>
50
- <DrawerTrigger asChild>
51
- <Button type="button" variant="outline">
52
- <Code2 />
53
- <span className="hidden sm:inline">Dev Mode</span>
54
- </Button>
49
+ <Drawer swipeDirection="right" onOpenChange={handleOpenChange}>
50
+ <DrawerTrigger render={<Button type="button" variant="outline" />}>
51
+ <Code2 />
52
+ <span className="hidden sm:inline">Dev Mode</span>
55
53
  </DrawerTrigger>
56
- <DrawerContent className="w-full overflow-hidden data-[vaul-drawer-direction=right]:sm:max-w-2xl data-[vaul-drawer-direction=right]:lg:max-w-4xl">
54
+ <DrawerContent className="w-full overflow-hidden data-[swipe-direction=right]:sm:max-w-2xl data-[swipe-direction=right]:lg:max-w-4xl">
57
55
  <DrawerHeader className="pb-4">
58
56
  <DrawerTitle>{integration.schemaLabel}</DrawerTitle>
59
57
  <DrawerDescription>
@@ -104,17 +104,16 @@ export function EntityFiltersBar({
104
104
  return (
105
105
  <div key={filter.key} className="relative flex items-center gap-1">
106
106
  <DropdownMenu>
107
- <DropdownMenuTrigger asChild>
108
- <Button variant="outline" className="w-45 justify-between">
109
- {filter.value
110
- ? (filter.options.find((o) => o.value === filter.value)?.label ??
111
- filter.label)
112
- : `All ${filter.label}`}
107
+ <DropdownMenuTrigger
108
+ render={<Button variant="outline" className="w-45 justify-between" />}
109
+ >
110
+ {filter.value
111
+ ? (filter.options.find((o) => o.value === filter.value)?.label ?? filter.label)
112
+ : `All ${filter.label}`}
113
113
 
114
- {!filter.value && (
115
- <ChevronDown className="absolute top-1/2 right-2.5 size-4 -translate-y-1/2 text-foreground" />
116
- )}
117
- </Button>
114
+ {!filter.value && (
115
+ <ChevronDown className="absolute top-1/2 right-2.5 size-4 -translate-y-1/2 text-foreground" />
116
+ )}
118
117
  </DropdownMenuTrigger>
119
118
  <DropdownMenuContent align="start">
120
119
  <DropdownMenuRadioGroup
@@ -36,10 +36,8 @@ export function EntityVersionItem({
36
36
  <Badge variant="secondary">v{version.version}</Badge>
37
37
  </div>
38
38
  <Tooltip>
39
- <TooltipTrigger asChild>
40
- <p className="w-fit text-xs text-muted-foreground">
41
- Saved {formatDistanceToNow(createdDate, { addSuffix: true })}
42
- </p>
39
+ <TooltipTrigger render={<p className="w-fit text-xs text-muted-foreground" />}>
40
+ Saved {formatDistanceToNow(createdDate, { addSuffix: true })}
43
41
  </TooltipTrigger>
44
42
  <TooltipContent>{format(createdDate, 'PPpp')}</TooltipContent>
45
43
  </Tooltip>
@@ -48,10 +48,8 @@ export function EntityVersionRestoreDialog({
48
48
 
49
49
  return (
50
50
  <AlertDialog open={open} onOpenChange={setOpen}>
51
- <AlertDialogTrigger asChild>
52
- <Button variant="outline" size="sm">
53
- Restore
54
- </Button>
51
+ <AlertDialogTrigger render={<Button variant="outline" size="sm" />}>
52
+ Restore
55
53
  </AlertDialogTrigger>
56
54
  <AlertDialogContent>
57
55
  <AlertDialogHeader>
@@ -34,10 +34,8 @@ export function EntityVersionsCurrentRow({ updatedAt, author }: EntityVersionsCu
34
34
  <Badge variant="outline">Current</Badge>
35
35
  </div>
36
36
  <Tooltip>
37
- <TooltipTrigger asChild>
38
- <p className="w-fit text-xs text-muted-foreground">
39
- Edited {formatDistanceToNow(updatedDate, { addSuffix: true })}
40
- </p>
37
+ <TooltipTrigger render={<p className="w-fit text-xs text-muted-foreground" />}>
38
+ Edited {formatDistanceToNow(updatedDate, { addSuffix: true })}
41
39
  </TooltipTrigger>
42
40
  <TooltipContent>{format(updatedDate, 'PPpp')}</TooltipContent>
43
41
  </Tooltip>
@@ -42,7 +42,7 @@ export function EntityVersionsDrawer({
42
42
  onRestored
43
43
  }: EntityVersionsDrawerProps) {
44
44
  return (
45
- <Drawer direction="right" open={open} onOpenChange={onOpenChange} modal>
45
+ <Drawer swipeDirection="right" open={open} onOpenChange={onOpenChange} modal>
46
46
  <DrawerContent className="h-full sm:max-w-lg">
47
47
  <DrawerHeader>
48
48
  <DrawerTitle>Versions</DrawerTitle>
@@ -31,10 +31,10 @@ export function EditMediaDialog({ media, open, onOpenChange, onSaved }: EditMedi
31
31
 
32
32
  return (
33
33
  <Drawer
34
- direction="right"
34
+ swipeDirection="right"
35
35
  open={isOpen}
36
36
  onOpenChange={handleOpenChange}
37
- onAnimationEnd={(nextOpen) => {
37
+ onOpenChangeComplete={(nextOpen) => {
38
38
  if (nextOpen) {
39
39
  setClosingMedia(null)
40
40
  return
@@ -52,11 +52,11 @@ export function MediaDeleteDialog({ media, disabled = false, onDeleted }: MediaD
52
52
 
53
53
  return (
54
54
  <AlertDialog>
55
- <AlertDialogTrigger asChild>
56
- <Button variant="destructive" disabled={disabled || isPending}>
57
- <Trash2 />
58
- Delete media
59
- </Button>
55
+ <AlertDialogTrigger
56
+ render={<Button variant="destructive" disabled={disabled || isPending} />}
57
+ >
58
+ <Trash2 />
59
+ Delete media
60
60
  </AlertDialogTrigger>
61
61
  <AlertDialogContent>
62
62
  <AlertDialogHeader>
@@ -4,10 +4,16 @@ import * as React from 'react'
4
4
  import type { AdminMedia } from '@admin/types'
5
5
  import { deleteMedia } from '@admin/actions/media'
6
6
  import { Button } from '@admin/components/ui/button'
7
+ import {
8
+ Drawer,
9
+ DrawerContent,
10
+ DrawerDescription,
11
+ DrawerTitle,
12
+ DrawerTrigger
13
+ } from '@admin/components/ui/drawer'
7
14
  import { Spinner } from '@admin/components/ui/spinner'
8
15
  import { Trash2, TriangleAlert } from 'lucide-react'
9
16
  import { toast } from 'sonner'
10
- import { Drawer as DrawerPrimitive } from 'vaul'
11
17
 
12
18
  interface MediaDeleteDrawerProps {
13
19
  media: AdminMedia
@@ -90,63 +96,56 @@ export function MediaDeleteDrawer({
90
96
  }
91
97
 
92
98
  return (
93
- <DrawerPrimitive.Root
99
+ <Drawer
94
100
  container={container}
95
- direction="bottom"
96
- dismissible={!isPending}
101
+ swipeDirection="down"
102
+ disablePointerDismissal={isPending}
97
103
  open={open}
98
104
  onOpenChange={handleOpenChange}
99
105
  >
100
- <DrawerPrimitive.Trigger asChild>
101
- <Button variant="destructive" disabled={disabled || isPending || !container}>
102
- <Trash2 />
103
- Delete media
104
- </Button>
105
- </DrawerPrimitive.Trigger>
106
- <DrawerPrimitive.Portal>
107
- <DrawerPrimitive.Overlay className="pointer-events-auto absolute inset-0 z-20 bg-black/45 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0" />
108
- <DrawerPrimitive.Content className="pointer-events-auto absolute inset-x-0 bottom-0 z-30 max-h-[calc(100%-1rem)] overflow-hidden p-3 outline-none">
109
- <div
110
- className="overflow-hidden rounded-sm border border-border bg-popover text-sm text-popover-foreground shadow-2xl transition-[height] duration-200 ease-out"
111
- style={contentHeight ? { height: contentHeight } : undefined}
112
- >
113
- <div
114
- ref={contentRef}
115
- className="max-h-[calc(100vh-8rem)] overflow-y-auto px-4 pt-4 pb-4"
116
- >
117
- <div aria-hidden="true" className="mx-auto mb-5 h-1.5 w-20 rounded-sm bg-muted" />
118
- <div className="mb-3 flex size-10 items-center justify-center rounded-sm bg-destructive/10 text-foreground">
119
- <TriangleAlert className="size-5" />
120
- </div>
121
- <DrawerPrimitive.Title className="font-heading text-base font-medium text-foreground">
122
- Delete this media?
123
- </DrawerPrimitive.Title>
124
- <DrawerPrimitive.Description className="mt-1 text-sm text-muted-foreground">
125
- This deletes {media.filename} from the media library. The stored file is not
126
- deleted.
127
- </DrawerPrimitive.Description>
128
- <div className="mt-5 grid grid-cols-2 gap-2">
129
- <Button
130
- variant="secondary"
131
- onClick={() => handleOpenChange(false)}
132
- disabled={isPending}
133
- >
134
- Cancel
135
- </Button>
136
- <Button
137
- variant="destructive"
138
- onClick={() => void handleDelete()}
139
- disabled={isPending}
140
- aria-busy={isPending}
141
- >
142
- {isPending && <Spinner />}
143
- {isPending ? 'Deleting…' : 'Delete media'}
144
- </Button>
145
- </div>
106
+ <DrawerTrigger
107
+ render={<Button variant="destructive" disabled={disabled || isPending || !container} />}
108
+ >
109
+ <Trash2 />
110
+ Delete media
111
+ </DrawerTrigger>
112
+ <DrawerContent className="pointer-events-auto max-h-[calc(100%-1rem)] overflow-hidden p-3 outline-none">
113
+ <div
114
+ className="overflow-hidden rounded-sm border border-border bg-popover text-sm text-popover-foreground shadow-2xl transition-[height] duration-200 ease-out"
115
+ style={contentHeight ? { height: contentHeight } : undefined}
116
+ >
117
+ <div ref={contentRef} className="max-h-[calc(100vh-8rem)] overflow-y-auto px-4 pt-4 pb-4">
118
+ <div aria-hidden="true" className="mx-auto mb-5 h-1.5 w-20 rounded-sm bg-muted" />
119
+ <div className="mb-3 flex size-10 items-center justify-center rounded-sm bg-destructive/10 text-foreground">
120
+ <TriangleAlert className="size-5" />
121
+ </div>
122
+ <DrawerTitle className="font-heading text-base font-medium text-foreground">
123
+ Delete this media?
124
+ </DrawerTitle>
125
+ <DrawerDescription className="mt-1 text-sm text-muted-foreground">
126
+ This deletes {media.filename} from the media library. The stored file is not deleted.
127
+ </DrawerDescription>
128
+ <div className="mt-5 grid grid-cols-2 gap-2">
129
+ <Button
130
+ variant="secondary"
131
+ onClick={() => handleOpenChange(false)}
132
+ disabled={isPending}
133
+ >
134
+ Cancel
135
+ </Button>
136
+ <Button
137
+ variant="destructive"
138
+ onClick={() => void handleDelete()}
139
+ disabled={isPending}
140
+ aria-busy={isPending}
141
+ >
142
+ {isPending && <Spinner />}
143
+ {isPending ? 'Deleting…' : 'Delete media'}
144
+ </Button>
146
145
  </div>
147
146
  </div>
148
- </DrawerPrimitive.Content>
149
- </DrawerPrimitive.Portal>
150
- </DrawerPrimitive.Root>
147
+ </div>
148
+ </DrawerContent>
149
+ </Drawer>
151
150
  )
152
151
  }
@@ -187,10 +187,10 @@ export function SortOrderDialog({
187
187
  onDragCancel={handleDragCancel}
188
188
  >
189
189
  <Drawer
190
- direction="right"
190
+ swipeDirection="right"
191
191
  open={open}
192
192
  onOpenChange={onOpenChange}
193
- onAnimationEnd={handleDrawerAnimationEnd}
193
+ onOpenChangeComplete={handleDrawerAnimationEnd}
194
194
  >
195
195
  <DrawerContent className="h-full w-full overflow-hidden">
196
196
  <div className="relative z-10 flex min-h-0 flex-1 flex-col gap-3 overflow-hidden">
@@ -231,9 +231,7 @@ export function SortOrderDialog({
231
231
  {isSaving && <Spinner />}
232
232
  {isSaving ? 'Saving…' : 'Save'}
233
233
  </Button>
234
- <DrawerClose asChild>
235
- <Button variant="outline">Close</Button>
236
- </DrawerClose>
234
+ <DrawerClose render={<Button variant="outline" />}>Close</DrawerClose>
237
235
  </DrawerFooter>
238
236
  </div>
239
237
  </DrawerContent>
@@ -51,7 +51,7 @@ export default function DashboardPage() {
51
51
  </p>
52
52
  </div>
53
53
  <div className="flex w-full flex-col">
54
- <Accordion type="single" collapsible defaultValue="item-1">
54
+ <Accordion defaultValue={['item-1']}>
55
55
  <AccordionItem value="item-1">
56
56
  <AccordionTrigger>
57
57
  <div className="flex items-center gap-3">
@@ -36,7 +36,7 @@ function formatMetadata(metadata: Record<string, unknown> | null): string {
36
36
 
37
37
  export function AuditLogDetailDrawer({ auditLog, open, onOpenChange }: AuditLogDetailDrawerProps) {
38
38
  return (
39
- <Drawer direction="right" open={open} onOpenChange={onOpenChange} modal>
39
+ <Drawer swipeDirection="right" open={open} onOpenChange={onOpenChange} modal>
40
40
  <DrawerContent className="h-full sm:max-w-xl">
41
41
  <DrawerHeader>
42
42
  <DrawerTitle>Audit Event</DrawerTitle>
@@ -82,7 +82,7 @@ export function FormNotificationsDrawer({
82
82
  const isPending = mutation.isPending
83
83
 
84
84
  return (
85
- <Drawer direction="right" open={open} onOpenChange={onOpenChange} modal>
85
+ <Drawer swipeDirection="right" open={open} onOpenChange={onOpenChange} modal>
86
86
  <DrawerContent className="h-full sm:max-w-xl">
87
87
  <Form {...form}>
88
88
  <form
@@ -128,10 +128,10 @@ export function FormNotificationsDrawer({
128
128
  </ScrollArea>
129
129
 
130
130
  <DrawerFooter className="flex-row justify-end">
131
- <DrawerClose asChild>
132
- <Button type="button" variant="outline" size="lg" disabled={isPending}>
133
- Cancel
134
- </Button>
131
+ <DrawerClose
132
+ render={<Button type="button" variant="outline" size="lg" disabled={isPending} />}
133
+ >
134
+ Cancel
135
135
  </DrawerClose>
136
136
  <Button
137
137
  type="submit"
@@ -23,33 +23,33 @@ export function WebhookActions({ webhook, onEdit, onDelete }: WebhookActionsProp
23
23
 
24
24
  return (
25
25
  <DropdownMenu>
26
- <DropdownMenuTrigger asChild>
27
- <Button
28
- variant="ghost"
29
- className="size-8 p-0"
30
- aria-label={`Open webhook actions for ${webhook.name}`}
31
- >
32
- <span className="sr-only">Open webhook actions</span>
33
- {sendTest.isPending ? (
34
- <Spinner className="size-4" />
35
- ) : (
36
- <MoreHorizontal className="size-4" />
37
- )}
38
- </Button>
39
- </DropdownMenuTrigger>
26
+ <DropdownMenuTrigger
27
+ render={
28
+ <Button
29
+ variant="ghost"
30
+ className="size-8 p-0"
31
+ aria-label={`Open webhook actions for ${webhook.name}`}
32
+ >
33
+ <span className="sr-only">Open webhook actions</span>
34
+ {sendTest.isPending ? (
35
+ <Spinner className="size-4" />
36
+ ) : (
37
+ <MoreHorizontal className="size-4" />
38
+ )}
39
+ </Button>
40
+ }
41
+ />
40
42
  <DropdownMenuContent align="end">
41
43
  <DropdownMenuItem
44
+ closeOnClick={false}
42
45
  disabled={sendTest.isPending}
43
46
  aria-busy={sendTest.isPending}
44
- onSelect={(event) => {
45
- event.preventDefault()
46
- sendTest.mutate(webhook.id)
47
- }}
47
+ onClick={() => sendTest.mutate(webhook.id)}
48
48
  >
49
49
  {sendTest.isPending ? 'Testing…' : 'Test'}
50
50
  </DropdownMenuItem>
51
- <DropdownMenuItem onSelect={() => onEdit(webhook)}>Edit</DropdownMenuItem>
52
- <DropdownMenuItem variant="destructive" onSelect={() => onDelete(webhook)}>
51
+ <DropdownMenuItem onClick={() => onEdit(webhook)}>Edit</DropdownMenuItem>
52
+ <DropdownMenuItem variant="destructive" onClick={() => onDelete(webhook)}>
53
53
  Delete
54
54
  </DropdownMenuItem>
55
55
  </DropdownMenuContent>
@@ -134,11 +134,13 @@ export function ChangePasswordDialog({
134
134
 
135
135
  return (
136
136
  <Dialog open={open} onOpenChange={handleOpenChange}>
137
- <DialogTrigger asChild>
138
- <DropdownMenuItem onSelect={(event) => event.preventDefault()}>
139
- <KeySquare className="size-4" />
140
- Change password
141
- </DropdownMenuItem>
137
+ <DialogTrigger
138
+ render={
139
+ <DropdownMenuItem closeOnClick={false} onClick={(event) => event.preventDefault()} />
140
+ }
141
+ >
142
+ <KeySquare className="size-4" />
143
+ Change password
142
144
  </DialogTrigger>
143
145
  <DialogContent className="sm:max-w-135">
144
146
  <Form {...form}>
@@ -148,11 +148,9 @@ export const columns: ColumnDef<User>[] = [
148
148
  return (
149
149
  <div className="flex justify-end">
150
150
  <DropdownMenu>
151
- <DropdownMenuTrigger asChild>
152
- <Button variant="ghost" className="size-8 p-0">
153
- <span className="sr-only">Open menu</span>
154
- <MoreHorizontal className="size-4" />
155
- </Button>
151
+ <DropdownMenuTrigger render={<Button variant="ghost" className="size-8 p-0" />}>
152
+ <span className="sr-only">Open menu</span>
153
+ <MoreHorizontal className="size-4" />
156
154
  </DropdownMenuTrigger>
157
155
  <DropdownMenuContent align="end">
158
156
  {!isCurrentUser ? (