@ploykit/ui 0.5.0 → 0.6.2

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 (222) hide show
  1. package/dist/AppProviders.js +2 -2
  2. package/dist/components/ConfirmDialog.js +1 -1
  3. package/dist/components/CronInput.js +3 -3
  4. package/dist/components/DataTable.js +4 -4
  5. package/dist/components/FormField.js +1 -1
  6. package/dist/components/ImpersonationBanner.js +1 -1
  7. package/dist/components/NotificationBell.js +1 -1
  8. package/dist/components/OnboardingChecklist.js +3 -3
  9. package/dist/components/Page.js +2 -2
  10. package/dist/components/ReauthDialog.js +4 -4
  11. package/dist/components/SecretModal.js +2 -2
  12. package/dist/components/SettingsCard.js +2 -2
  13. package/dist/components/SiteBanner.js +1 -1
  14. package/dist/components/SiteBannerLayer.js +1 -1
  15. package/dist/components/StatusBadge.js +1 -1
  16. package/dist/components/UserMenu.js +3 -3
  17. package/dist/components/WorkspaceSwitcher.js +7 -7
  18. package/dist/components/ui/alert-dialog.js +2 -2
  19. package/dist/components/ui/avatar.js +1 -1
  20. package/dist/components/ui/badge.js +1 -1
  21. package/dist/components/ui/breadcrumb.js +1 -1
  22. package/dist/components/ui/button.js +1 -1
  23. package/dist/components/ui/card.js +1 -1
  24. package/dist/components/ui/checkbox.js +1 -1
  25. package/dist/components/ui/dialog.js +2 -2
  26. package/dist/components/ui/dropdown-menu.js +1 -1
  27. package/dist/components/ui/empty.js +1 -1
  28. package/dist/components/ui/field.js +3 -3
  29. package/dist/components/ui/input.js +1 -1
  30. package/dist/components/ui/label.js +1 -1
  31. package/dist/components/ui/popover.js +1 -1
  32. package/dist/components/ui/progress.js +1 -1
  33. package/dist/components/ui/select.js +1 -1
  34. package/dist/components/ui/separator.js +1 -1
  35. package/dist/components/ui/sheet.js +2 -2
  36. package/dist/components/ui/sidebar.js +8 -8
  37. package/dist/components/ui/skeleton.js +1 -1
  38. package/dist/components/ui/switch.js +1 -1
  39. package/dist/components/ui/tabs.js +1 -1
  40. package/dist/components/ui/textarea.js +1 -1
  41. package/dist/components/ui/tooltip.js +1 -1
  42. package/dist/index.js +78 -78
  43. package/dist/layouts/AppShell.js +4 -4
  44. package/dist/layouts/SettingsShell.js +4 -4
  45. package/dist/pages/LoginPage.js +5 -5
  46. package/dist/pages/account/NotificationPreferencesPage.js +3 -3
  47. package/dist/pages/account/ProfileSettingsPage.js +9 -9
  48. package/dist/pages/account/SecuritySettingsPage.js +13 -13
  49. package/dist/pages/account/TokensPage.js +12 -12
  50. package/dist/pages/admin/AdminSettingsPage.js +11 -11
  51. package/dist/pages/admin/AdminShell.js +3 -3
  52. package/dist/pages/admin/AuditPage.js +8 -8
  53. package/dist/pages/admin/OrdersPage.js +12 -12
  54. package/dist/pages/admin/OverviewPage.js +13 -13
  55. package/dist/pages/admin/SSOPage.js +6 -6
  56. package/dist/pages/admin/UserDetailPage.js +13 -13
  57. package/dist/pages/admin/UsersPage.js +13 -13
  58. package/dist/pages/admin/WebhookDeliveriesPage.js +9 -9
  59. package/dist/pages/admin/WorkspaceDetailPage.js +14 -14
  60. package/dist/pages/admin/WorkspacesPage.js +9 -9
  61. package/dist/pages/admin/shared.js +1 -1
  62. package/dist/pages/auth/ForgotPasswordPage.js +4 -4
  63. package/dist/pages/auth/InviteAcceptPage.js +6 -6
  64. package/dist/pages/auth/RegisterPage.js +7 -7
  65. package/dist/pages/auth/ResetPasswordPage.js +5 -5
  66. package/dist/pages/auth/VerifyEmailPage.js +3 -3
  67. package/dist/pages/workspace/BillingPage.js +11 -11
  68. package/dist/pages/workspace/BillingSuccessPage.js +2 -2
  69. package/dist/pages/workspace/MembersPage.js +15 -15
  70. package/dist/pages/workspace/RolePermissionsPage.js +9 -9
  71. package/dist/pages/workspace/SchedulesPage.js +12 -12
  72. package/dist/pages/workspace/UsagePage.js +6 -6
  73. package/dist/pages/workspace/WebhooksPage.js +16 -16
  74. package/dist/pages/workspace/WorkspaceAuditPage.js +7 -7
  75. package/dist/pages/workspace/WorkspaceGeneralPage.js +9 -9
  76. package/package.json +6 -5
  77. package/src/AppProviders.tsx +29 -0
  78. package/src/components/ConfirmDialog.tsx +77 -0
  79. package/src/components/CronInput.tsx +195 -0
  80. package/src/components/DataTable.tsx +152 -0
  81. package/src/components/ErrorBoundary.tsx +46 -0
  82. package/src/components/FormField.tsx +56 -0
  83. package/src/components/ImpersonationBanner.tsx +23 -0
  84. package/src/components/NotificationBell.tsx +135 -0
  85. package/src/components/OnboardingChecklist.tsx +114 -0
  86. package/src/components/Page.tsx +67 -0
  87. package/src/components/ReauthDialog.tsx +94 -0
  88. package/src/components/SecretModal.tsx +147 -0
  89. package/src/components/SettingsCard.tsx +39 -0
  90. package/src/components/SiteBanner.tsx +32 -0
  91. package/src/components/SiteBannerLayer.tsx +29 -0
  92. package/src/components/StatusBadge.tsx +12 -0
  93. package/src/components/UserMenu.tsx +103 -0
  94. package/src/components/WorkspaceSwitcher.tsx +159 -0
  95. package/src/components/__tests__/AppProviders.test.tsx +111 -0
  96. package/src/components/__tests__/CronInput.test.tsx +180 -0
  97. package/src/components/__tests__/DataTable.test.tsx +208 -0
  98. package/src/components/__tests__/ErrorBoundary.test.tsx +61 -0
  99. package/src/components/__tests__/ImpersonationBanner.test.tsx +59 -0
  100. package/src/components/__tests__/NotificationBell.test.tsx +207 -0
  101. package/src/components/__tests__/OnboardingChecklist.test.tsx +97 -0
  102. package/src/components/__tests__/SecretModal.test.tsx +112 -0
  103. package/src/components/__tests__/SiteBannerLayer.test.tsx +44 -0
  104. package/src/components/__tests__/UserMenu.test.tsx +98 -0
  105. package/src/components/__tests__/WorkspaceSwitcher.test.tsx +162 -0
  106. package/src/components/__tests__/form.test.tsx +133 -0
  107. package/src/components/__tests__/semantic-tokens.test.ts +41 -0
  108. package/src/components/__tests__/smoke.test.tsx +11 -0
  109. package/src/components/__tests__/toast.test.tsx +27 -0
  110. package/src/components/toast.tsx +23 -0
  111. package/src/components/ui/__tests__/alert-dialog.test.tsx +66 -0
  112. package/src/components/ui/__tests__/avatar.test.tsx +30 -0
  113. package/src/components/ui/__tests__/checkbox.test.tsx +18 -0
  114. package/src/components/ui/__tests__/dropdown-menu.test.tsx +33 -0
  115. package/src/components/ui/__tests__/field.test.tsx +43 -0
  116. package/src/components/ui/__tests__/overlay-size.test.tsx +84 -0
  117. package/src/components/ui/__tests__/popover.test.tsx +32 -0
  118. package/src/components/ui/__tests__/progress.test.tsx +24 -0
  119. package/src/components/ui/__tests__/select-callback.test.tsx +72 -0
  120. package/src/components/ui/__tests__/select.test.tsx +48 -0
  121. package/src/components/ui/__tests__/sidebar.test.tsx +121 -0
  122. package/src/components/ui/__tests__/stock-mirror.test.ts +39 -0
  123. package/src/components/ui/__tests__/subpath.test.tsx +38 -0
  124. package/src/components/ui/__tests__/switch.test.tsx +24 -0
  125. package/src/components/ui/__tests__/tabs.test.tsx +24 -0
  126. package/src/components/ui/__tests__/textarea.test.tsx +41 -0
  127. package/src/components/ui/alert-dialog.tsx +187 -0
  128. package/src/components/ui/avatar.tsx +108 -0
  129. package/src/components/ui/badge.tsx +51 -0
  130. package/src/components/ui/breadcrumb.tsx +124 -0
  131. package/src/components/ui/button.tsx +57 -0
  132. package/src/components/ui/card.tsx +102 -0
  133. package/src/components/ui/checkbox.tsx +28 -0
  134. package/src/components/ui/dialog.tsx +166 -0
  135. package/src/components/ui/dropdown-menu.tsx +265 -0
  136. package/src/components/ui/empty.tsx +103 -0
  137. package/src/components/ui/field.tsx +238 -0
  138. package/src/components/ui/input.tsx +19 -0
  139. package/src/components/ui/label.tsx +17 -0
  140. package/src/components/ui/popover.tsx +89 -0
  141. package/src/components/ui/progress.tsx +82 -0
  142. package/src/components/ui/select.tsx +235 -0
  143. package/src/components/ui/separator.tsx +24 -0
  144. package/src/components/ui/sheet.tsx +146 -0
  145. package/src/components/ui/sidebar.tsx +723 -0
  146. package/src/components/ui/skeleton.tsx +13 -0
  147. package/src/components/ui/switch.tsx +29 -0
  148. package/src/components/ui/tabs.tsx +79 -0
  149. package/src/components/ui/textarea.tsx +26 -0
  150. package/src/components/ui/tooltip.tsx +63 -0
  151. package/src/dev.css +1 -0
  152. package/src/hooks/use-mobile.ts +19 -0
  153. package/src/index.ts +150 -0
  154. package/src/layouts/AppShell.tsx +163 -0
  155. package/src/layouts/AuthShell.tsx +24 -0
  156. package/src/layouts/SettingsShell.tsx +129 -0
  157. package/src/layouts/__tests__/AppShell.test.tsx +163 -0
  158. package/src/layouts/__tests__/SettingsShell.test.tsx +146 -0
  159. package/src/lib/__tests__/api-error.test.ts +163 -0
  160. package/src/lib/__tests__/utils.test.ts +21 -0
  161. package/src/lib/api-error.ts +98 -0
  162. package/src/lib/utils.ts +109 -0
  163. package/src/pages/LandingPage.tsx +88 -0
  164. package/src/pages/LoginPage.tsx +291 -0
  165. package/src/pages/__tests__/LandingPage.test.tsx +58 -0
  166. package/src/pages/__tests__/LoginPage.test.tsx +229 -0
  167. package/src/pages/__tests__/RegisterPage.test.tsx +138 -0
  168. package/src/pages/__tests__/ssr-smoke.test.tsx +99 -0
  169. package/src/pages/account/NotificationPreferencesPage.tsx +138 -0
  170. package/src/pages/account/ProfileSettingsPage.tsx +189 -0
  171. package/src/pages/account/SecuritySettingsPage.tsx +214 -0
  172. package/src/pages/account/TokensPage.tsx +211 -0
  173. package/src/pages/account/__tests__/NotificationPreferencesPage.test.tsx +150 -0
  174. package/src/pages/account/__tests__/ProfileSettingsPage.test.tsx +173 -0
  175. package/src/pages/account/__tests__/SecuritySettingsPage.test.tsx +212 -0
  176. package/src/pages/account/__tests__/TokensPage.test.tsx +180 -0
  177. package/src/pages/admin/AdminSettingsPage.tsx +564 -0
  178. package/src/pages/admin/AdminShell.tsx +199 -0
  179. package/src/pages/admin/AuditPage.tsx +338 -0
  180. package/src/pages/admin/OrdersPage.tsx +642 -0
  181. package/src/pages/admin/OverviewPage.tsx +559 -0
  182. package/src/pages/admin/SSOPage.tsx +166 -0
  183. package/src/pages/admin/UserDetailPage.tsx +641 -0
  184. package/src/pages/admin/UsersPage.tsx +462 -0
  185. package/src/pages/admin/WebhookDeliveriesPage.tsx +318 -0
  186. package/src/pages/admin/WorkspaceDetailPage.tsx +551 -0
  187. package/src/pages/admin/WorkspacesPage.tsx +299 -0
  188. package/src/pages/admin/__tests__/AdminSettingsPage.test.tsx +260 -0
  189. package/src/pages/admin/__tests__/OrdersPageMarkPaid.test.tsx +207 -0
  190. package/src/pages/admin/__tests__/OverviewPageActivity.test.tsx +213 -0
  191. package/src/pages/admin/__tests__/SSOPage.test.tsx +128 -0
  192. package/src/pages/admin/__tests__/UsersPageActions.test.tsx +188 -0
  193. package/src/pages/admin/__tests__/WorkspaceDetailPageTransfer.test.tsx +170 -0
  194. package/src/pages/admin/__tests__/WorkspacesPagePlans.test.tsx +138 -0
  195. package/src/pages/admin/shared.ts +42 -0
  196. package/src/pages/auth/ForgotPasswordPage.tsx +83 -0
  197. package/src/pages/auth/InviteAcceptPage.tsx +105 -0
  198. package/src/pages/auth/RegisterPage.tsx +204 -0
  199. package/src/pages/auth/ResetPasswordPage.tsx +150 -0
  200. package/src/pages/auth/VerifyEmailPage.tsx +76 -0
  201. package/src/pages/auth/__tests__/ForgotPasswordPage.test.tsx +67 -0
  202. package/src/pages/auth/__tests__/InviteAcceptPage.test.tsx +86 -0
  203. package/src/pages/auth/__tests__/ResetPasswordPage.test.tsx +115 -0
  204. package/src/pages/auth/__tests__/VerifyEmailPage.test.tsx +74 -0
  205. package/src/pages/workspace/BillingPage.tsx +361 -0
  206. package/src/pages/workspace/BillingSuccessPage.tsx +115 -0
  207. package/src/pages/workspace/MembersPage.tsx +568 -0
  208. package/src/pages/workspace/RolePermissionsPage.tsx +202 -0
  209. package/src/pages/workspace/SchedulesPage.tsx +387 -0
  210. package/src/pages/workspace/UsagePage.tsx +207 -0
  211. package/src/pages/workspace/WebhooksPage.tsx +506 -0
  212. package/src/pages/workspace/WorkspaceAuditPage.tsx +229 -0
  213. package/src/pages/workspace/WorkspaceGeneralPage.tsx +184 -0
  214. package/src/pages/workspace/__tests__/BillingPage.test.tsx +302 -0
  215. package/src/pages/workspace/__tests__/BillingSuccessPage.test.tsx +134 -0
  216. package/src/pages/workspace/__tests__/MembersPage.test.tsx +347 -0
  217. package/src/pages/workspace/__tests__/RolePermissionsPage.test.tsx +138 -0
  218. package/src/pages/workspace/__tests__/SchedulesPage.test.tsx +239 -0
  219. package/src/pages/workspace/__tests__/UsagePage.test.tsx +223 -0
  220. package/src/pages/workspace/__tests__/WebhooksPage.test.tsx +309 -0
  221. package/src/pages/workspace/__tests__/WorkspaceAuditPage.test.tsx +112 -0
  222. package/src/pages/workspace/__tests__/WorkspaceGeneralPage.test.tsx +164 -0
@@ -0,0 +1,166 @@
1
+ import * as React from "react"
2
+ import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"
3
+ import { cn } from "../../lib/utils"
4
+
5
+ import { Button } from "./button"
6
+ import { XIcon } from "lucide-react"
7
+
8
+ function Dialog({ ...props }: DialogPrimitive.Root.Props) {
9
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />
10
+ }
11
+
12
+ function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {
13
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
14
+ }
15
+
16
+ function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {
17
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
18
+ }
19
+
20
+ function DialogClose({ ...props }: DialogPrimitive.Close.Props) {
21
+ return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
22
+ }
23
+
24
+ function DialogOverlay({
25
+ className,
26
+ ...props
27
+ }: DialogPrimitive.Backdrop.Props) {
28
+ return (
29
+ <DialogPrimitive.Backdrop
30
+ data-slot="dialog-overlay"
31
+ className={cn(
32
+ "fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
33
+ className
34
+ )}
35
+ {...props}
36
+ />
37
+ )
38
+ }
39
+
40
+ /**
41
+ * DialogContent 内容面板。size 控制最大宽度档位(经 data-size 落到
42
+ * Tailwind data-[size=*] 变体):sm=sm:max-w-sm(默认,历史视觉)/
43
+ * md=sm:max-w-lg / lg=sm:max-w-2xl / xl=sm:max-w-4xl。
44
+ */
45
+ function DialogContent({
46
+ className,
47
+ children,
48
+ size = "sm",
49
+ showCloseButton = true,
50
+ ...props
51
+ }: DialogPrimitive.Popup.Props & {
52
+ size?: "sm" | "md" | "lg" | "xl"
53
+ showCloseButton?: boolean
54
+ }) {
55
+ return (
56
+ <DialogPortal>
57
+ <DialogOverlay />
58
+ <DialogPrimitive.Popup
59
+ data-slot="dialog-content"
60
+ data-size={size}
61
+ className={cn(
62
+ "fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[size=md]:sm:max-w-lg data-[size=lg]:sm:max-w-2xl data-[size=xl]:sm:max-w-4xl",
63
+ className
64
+ )}
65
+ {...props}
66
+ >
67
+ {children}
68
+ {showCloseButton && (
69
+ <DialogPrimitive.Close
70
+ data-slot="dialog-close"
71
+ render={
72
+ <Button
73
+ variant="ghost"
74
+ className="absolute top-2 right-2"
75
+ size="icon-sm"
76
+ />
77
+ }
78
+ >
79
+ <XIcon
80
+ />
81
+ <span className="sr-only">Close</span>
82
+ </DialogPrimitive.Close>
83
+ )}
84
+ </DialogPrimitive.Popup>
85
+ </DialogPortal>
86
+ )
87
+ }
88
+
89
+ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
90
+ return (
91
+ <div
92
+ data-slot="dialog-header"
93
+ className={cn("flex flex-col gap-2", className)}
94
+ {...props}
95
+ />
96
+ )
97
+ }
98
+
99
+ function DialogFooter({
100
+ className,
101
+ showCloseButton = false,
102
+ children,
103
+ ...props
104
+ }: React.ComponentProps<"div"> & {
105
+ showCloseButton?: boolean
106
+ }) {
107
+ return (
108
+ <div
109
+ data-slot="dialog-footer"
110
+ className={cn(
111
+ "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end",
112
+ className
113
+ )}
114
+ {...props}
115
+ >
116
+ {children}
117
+ {showCloseButton && (
118
+ <DialogPrimitive.Close render={<Button variant="outline" />}>
119
+ Close
120
+ </DialogPrimitive.Close>
121
+ )}
122
+ </div>
123
+ )
124
+ }
125
+
126
+ function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
127
+ return (
128
+ <DialogPrimitive.Title
129
+ data-slot="dialog-title"
130
+ className={cn(
131
+ "text-base leading-none font-medium",
132
+ className
133
+ )}
134
+ {...props}
135
+ />
136
+ )
137
+ }
138
+
139
+ function DialogDescription({
140
+ className,
141
+ ...props
142
+ }: DialogPrimitive.Description.Props) {
143
+ return (
144
+ <DialogPrimitive.Description
145
+ data-slot="dialog-description"
146
+ className={cn(
147
+ "text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
148
+ className
149
+ )}
150
+ {...props}
151
+ />
152
+ )
153
+ }
154
+
155
+ export {
156
+ Dialog,
157
+ DialogClose,
158
+ DialogContent,
159
+ DialogDescription,
160
+ DialogFooter,
161
+ DialogHeader,
162
+ DialogOverlay,
163
+ DialogPortal,
164
+ DialogTitle,
165
+ DialogTrigger,
166
+ }
@@ -0,0 +1,265 @@
1
+ import * as React from "react"
2
+ import { Menu as MenuPrimitive } from "@base-ui/react/menu"
3
+ import { cn } from "../../lib/utils"
4
+ import { ChevronRightIcon, CheckIcon } from "lucide-react"
5
+
6
+ function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
7
+ return <MenuPrimitive.Root data-slot="dropdown-menu" {...props} />
8
+ }
9
+
10
+ function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
11
+ return <MenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
12
+ }
13
+
14
+ function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
15
+ return <MenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />
16
+ }
17
+
18
+ function DropdownMenuContent({
19
+ align = "start",
20
+ alignOffset = 0,
21
+ side = "bottom",
22
+ sideOffset = 4,
23
+ className,
24
+ ...props
25
+ }: MenuPrimitive.Popup.Props &
26
+ Pick<
27
+ MenuPrimitive.Positioner.Props,
28
+ "align" | "alignOffset" | "side" | "sideOffset"
29
+ >) {
30
+ return (
31
+ <MenuPrimitive.Portal>
32
+ <MenuPrimitive.Positioner
33
+ className="isolate z-50 outline-none"
34
+ align={align}
35
+ alignOffset={alignOffset}
36
+ side={side}
37
+ sideOffset={sideOffset}
38
+ >
39
+ <MenuPrimitive.Popup
40
+ data-slot="dropdown-menu-content"
41
+ className={cn("z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95", className )}
42
+ {...props}
43
+ />
44
+ </MenuPrimitive.Positioner>
45
+ </MenuPrimitive.Portal>
46
+ )
47
+ }
48
+
49
+ function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
50
+ return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
51
+ }
52
+
53
+ function DropdownMenuLabel({
54
+ className,
55
+ inset,
56
+ ...props
57
+ }: MenuPrimitive.GroupLabel.Props & {
58
+ inset?: boolean
59
+ }) {
60
+ return (
61
+ <MenuPrimitive.GroupLabel
62
+ data-slot="dropdown-menu-label"
63
+ data-inset={inset}
64
+ className={cn(
65
+ "px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7",
66
+ className
67
+ )}
68
+ {...props}
69
+ />
70
+ )
71
+ }
72
+
73
+ function DropdownMenuItem({
74
+ className,
75
+ inset,
76
+ variant = "default",
77
+ ...props
78
+ }: MenuPrimitive.Item.Props & {
79
+ inset?: boolean
80
+ variant?: "default" | "destructive"
81
+ }) {
82
+ return (
83
+ <MenuPrimitive.Item
84
+ data-slot="dropdown-menu-item"
85
+ data-inset={inset}
86
+ data-variant={variant}
87
+ className={cn(
88
+ "group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
89
+ className
90
+ )}
91
+ {...props}
92
+ />
93
+ )
94
+ }
95
+
96
+ function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {
97
+ return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />
98
+ }
99
+
100
+ function DropdownMenuSubTrigger({
101
+ className,
102
+ inset,
103
+ children,
104
+ ...props
105
+ }: MenuPrimitive.SubmenuTrigger.Props & {
106
+ inset?: boolean
107
+ }) {
108
+ return (
109
+ <MenuPrimitive.SubmenuTrigger
110
+ data-slot="dropdown-menu-sub-trigger"
111
+ data-inset={inset}
112
+ className={cn(
113
+ "flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
114
+ className
115
+ )}
116
+ {...props}
117
+ >
118
+ {children}
119
+ <ChevronRightIcon className="ml-auto" />
120
+ </MenuPrimitive.SubmenuTrigger>
121
+ )
122
+ }
123
+
124
+ function DropdownMenuSubContent({
125
+ align = "start",
126
+ alignOffset = -3,
127
+ side = "right",
128
+ sideOffset = 0,
129
+ className,
130
+ ...props
131
+ }: React.ComponentProps<typeof DropdownMenuContent>) {
132
+ return (
133
+ <DropdownMenuContent
134
+ data-slot="dropdown-menu-sub-content"
135
+ className={cn("w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
136
+ align={align}
137
+ alignOffset={alignOffset}
138
+ side={side}
139
+ sideOffset={sideOffset}
140
+ {...props}
141
+ />
142
+ )
143
+ }
144
+
145
+ function DropdownMenuCheckboxItem({
146
+ className,
147
+ children,
148
+ checked,
149
+ inset,
150
+ ...props
151
+ }: MenuPrimitive.CheckboxItem.Props & {
152
+ inset?: boolean
153
+ }) {
154
+ return (
155
+ <MenuPrimitive.CheckboxItem
156
+ data-slot="dropdown-menu-checkbox-item"
157
+ data-inset={inset}
158
+ className={cn(
159
+ "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
160
+ className
161
+ )}
162
+ checked={checked}
163
+ {...props}
164
+ >
165
+ <span
166
+ className="pointer-events-none absolute right-2 flex items-center justify-center"
167
+ data-slot="dropdown-menu-checkbox-item-indicator"
168
+ >
169
+ <MenuPrimitive.CheckboxItemIndicator>
170
+ <CheckIcon
171
+ />
172
+ </MenuPrimitive.CheckboxItemIndicator>
173
+ </span>
174
+ {children}
175
+ </MenuPrimitive.CheckboxItem>
176
+ )
177
+ }
178
+
179
+ function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {
180
+ return (
181
+ <MenuPrimitive.RadioGroup
182
+ data-slot="dropdown-menu-radio-group"
183
+ {...props}
184
+ />
185
+ )
186
+ }
187
+
188
+ function DropdownMenuRadioItem({
189
+ className,
190
+ children,
191
+ inset,
192
+ ...props
193
+ }: MenuPrimitive.RadioItem.Props & {
194
+ inset?: boolean
195
+ }) {
196
+ return (
197
+ <MenuPrimitive.RadioItem
198
+ data-slot="dropdown-menu-radio-item"
199
+ data-inset={inset}
200
+ className={cn(
201
+ "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
202
+ className
203
+ )}
204
+ {...props}
205
+ >
206
+ <span
207
+ className="pointer-events-none absolute right-2 flex items-center justify-center"
208
+ data-slot="dropdown-menu-radio-item-indicator"
209
+ >
210
+ <MenuPrimitive.RadioItemIndicator>
211
+ <CheckIcon
212
+ />
213
+ </MenuPrimitive.RadioItemIndicator>
214
+ </span>
215
+ {children}
216
+ </MenuPrimitive.RadioItem>
217
+ )
218
+ }
219
+
220
+ function DropdownMenuSeparator({
221
+ className,
222
+ ...props
223
+ }: MenuPrimitive.Separator.Props) {
224
+ return (
225
+ <MenuPrimitive.Separator
226
+ data-slot="dropdown-menu-separator"
227
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
228
+ {...props}
229
+ />
230
+ )
231
+ }
232
+
233
+ function DropdownMenuShortcut({
234
+ className,
235
+ ...props
236
+ }: React.ComponentProps<"span">) {
237
+ return (
238
+ <span
239
+ data-slot="dropdown-menu-shortcut"
240
+ className={cn(
241
+ "ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground",
242
+ className
243
+ )}
244
+ {...props}
245
+ />
246
+ )
247
+ }
248
+
249
+ export {
250
+ DropdownMenu,
251
+ DropdownMenuPortal,
252
+ DropdownMenuTrigger,
253
+ DropdownMenuContent,
254
+ DropdownMenuGroup,
255
+ DropdownMenuLabel,
256
+ DropdownMenuItem,
257
+ DropdownMenuCheckboxItem,
258
+ DropdownMenuRadioGroup,
259
+ DropdownMenuRadioItem,
260
+ DropdownMenuSeparator,
261
+ DropdownMenuShortcut,
262
+ DropdownMenuSub,
263
+ DropdownMenuSubTrigger,
264
+ DropdownMenuSubContent,
265
+ }
@@ -0,0 +1,103 @@
1
+ import { cva, type VariantProps } from "class-variance-authority"
2
+ import { cn } from "../../lib/utils"
3
+
4
+ function Empty({ className, ...props }: React.ComponentProps<"div">) {
5
+ return (
6
+ <div
7
+ data-slot="empty"
8
+ className={cn(
9
+ "flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-xl border-dashed p-6 text-center text-balance",
10
+ className
11
+ )}
12
+ {...props}
13
+ />
14
+ )
15
+ }
16
+
17
+ function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
18
+ return (
19
+ <div
20
+ data-slot="empty-header"
21
+ className={cn("flex max-w-sm flex-col items-center gap-2", className)}
22
+ {...props}
23
+ />
24
+ )
25
+ }
26
+
27
+ const emptyMediaVariants = cva(
28
+ "mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
29
+ {
30
+ variants: {
31
+ variant: {
32
+ default: "bg-transparent",
33
+ icon: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-4",
34
+ },
35
+ },
36
+ defaultVariants: {
37
+ variant: "default",
38
+ },
39
+ }
40
+ )
41
+
42
+ function EmptyMedia({
43
+ className,
44
+ variant = "default",
45
+ ...props
46
+ }: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
47
+ return (
48
+ <div
49
+ data-slot="empty-icon"
50
+ data-variant={variant}
51
+ className={cn(emptyMediaVariants({ variant, className }))}
52
+ {...props}
53
+ />
54
+ )
55
+ }
56
+
57
+ function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
58
+ return (
59
+ <div
60
+ data-slot="empty-title"
61
+ className={cn(
62
+ "text-sm font-medium tracking-tight",
63
+ className
64
+ )}
65
+ {...props}
66
+ />
67
+ )
68
+ }
69
+
70
+ function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
71
+ return (
72
+ <div
73
+ data-slot="empty-description"
74
+ className={cn(
75
+ "text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
76
+ className
77
+ )}
78
+ {...props}
79
+ />
80
+ )
81
+ }
82
+
83
+ function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
84
+ return (
85
+ <div
86
+ data-slot="empty-content"
87
+ className={cn(
88
+ "flex w-full max-w-sm min-w-0 flex-col items-center gap-2.5 text-sm text-balance",
89
+ className
90
+ )}
91
+ {...props}
92
+ />
93
+ )
94
+ }
95
+
96
+ export {
97
+ Empty,
98
+ EmptyHeader,
99
+ EmptyTitle,
100
+ EmptyDescription,
101
+ EmptyContent,
102
+ EmptyMedia,
103
+ }