@allbluecn/admin-app 0.3.2 → 0.3.3

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 (198) hide show
  1. package/package.json +19 -17
  2. package/src/components/admin/admin-user-menu.tsx +4 -4
  3. package/src/components/admin/developer-log.tsx +16 -32
  4. package/src/components/ai-memory/memory-facts-panel.tsx +30 -70
  5. package/src/components/ai-prompts/preview-panel.tsx +1 -1
  6. package/src/components/ai-prompts/prompt-editor.tsx +8 -9
  7. package/src/components/ai-prompts/prompt-table.tsx +6 -6
  8. package/src/components/ai-prompts/section-editor.tsx +3 -3
  9. package/src/components/ai-prompts/variable-panel.tsx +2 -2
  10. package/src/components/ai-prompts/version-history.tsx +21 -41
  11. package/src/components/ai-provider/model-list-editor.tsx +2 -3
  12. package/src/components/ai-provider/provider-form.tsx +7 -7
  13. package/src/components/ai-provider/provider-table.tsx +17 -40
  14. package/src/components/auth/admin-login-form.tsx +7 -7
  15. package/src/components/auth/icon-input.tsx +2 -2
  16. package/src/components/auth/password-input.tsx +2 -2
  17. package/src/components/component/component-form-dialog.tsx +10 -18
  18. package/src/components/component/component-import-dialog.tsx +6 -6
  19. package/src/components/component/component-preview.tsx +311 -0
  20. package/src/components/component/component-table.tsx +3 -3
  21. package/src/components/dependency/changelog-dialog.tsx +2 -2
  22. package/src/components/dependency/columns.tsx +3 -3
  23. package/src/components/dependency/dependency-table.tsx +7 -7
  24. package/src/components/dependency/edit-dialog.tsx +8 -8
  25. package/src/components/invitations/invitations-page.tsx +26 -49
  26. package/src/components/knowledge-public/bookmark-form-dialog.tsx +6 -6
  27. package/src/components/knowledge-public/compliance-form-dialog.tsx +6 -6
  28. package/src/components/knowledge-public/legal-form-dialog.tsx +7 -7
  29. package/src/components/layout/sidebar-02/app-sidebar.tsx +1 -2
  30. package/src/components/layout/sidebar-02/index.tsx +1 -1
  31. package/src/components/layout/sidebar-02/nav-main.tsx +2 -3
  32. package/src/components/layout/sidebar-02/nav-notifications.tsx +3 -3
  33. package/src/components/market/columns.tsx +4 -4
  34. package/src/components/market/market-app-form.tsx +6 -7
  35. package/src/components/market/market-app-list.tsx +14 -29
  36. package/src/components/monitoring/error-list.tsx +2 -2
  37. package/src/components/monitoring/metrics-stats.tsx +1 -1
  38. package/src/components/monitoring/request-log-table.tsx +2 -2
  39. package/src/components/oauth-providers/provider-page.tsx +20 -38
  40. package/src/components/permissions/assign-dialog.tsx +135 -0
  41. package/src/components/permissions/create-role-dialog.tsx +135 -0
  42. package/src/components/permissions/types.ts +49 -0
  43. package/src/components/user/columns.tsx +6 -6
  44. package/src/components/user/settings-activity-log.tsx +7 -7
  45. package/src/components/user/settings-profile/avatar-uploader.tsx +118 -0
  46. package/src/components/user/settings-profile/social-links.tsx +63 -0
  47. package/src/components/user/settings-profile.tsx +26 -125
  48. package/src/components/user/user-create-dialog.tsx +6 -6
  49. package/src/components/user/user-detail/error-boundary.tsx +19 -0
  50. package/src/components/user/user-detail/user-detail-dialogs.tsx +203 -0
  51. package/src/components/user/user-filters.tsx +4 -4
  52. package/src/lib/auth/page-gate.ts +28 -0
  53. package/src/lib/auth.config.ts +25 -9
  54. package/src/lib/i18n/detect.ts +1 -1
  55. package/src/lib/loader-serial.ts +14 -0
  56. package/src/providers/index.tsx +1 -1
  57. package/src/routeTree.gen.ts +67 -78
  58. package/src/routes/__root.tsx +4 -4
  59. package/src/routes/_nav/audit/route.lazy.tsx +1 -2
  60. package/src/routes/_nav/compliance/route.lazy.tsx +5 -3
  61. package/src/routes/_nav/components/route.lazy.tsx +14 -34
  62. package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +18 -38
  63. package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +18 -38
  64. package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +6 -6
  65. package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +3 -3
  66. package/src/routes/_nav/licenses/new/route.lazy.tsx +5 -5
  67. package/src/routes/_nav/licenses/route.lazy.tsx +1 -1
  68. package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +2 -2
  69. package/src/routes/_nav/monitoring/errors/route.lazy.tsx +10 -10
  70. package/src/routes/_nav/monitoring/errors/route.tsx +7 -0
  71. package/src/routes/_nav/monitoring/health/route.lazy.tsx +13 -15
  72. package/src/routes/_nav/monitoring/health/route.tsx +14 -0
  73. package/src/routes/_nav/monitoring/logs/route.lazy.tsx +24 -9
  74. package/src/routes/_nav/monitoring/logs/route.tsx +13 -0
  75. package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +12 -14
  76. package/src/routes/_nav/monitoring/metrics/route.tsx +7 -0
  77. package/src/routes/_nav/monitoring/overview/route.lazy.tsx +14 -13
  78. package/src/routes/_nav/monitoring/overview/route.tsx +17 -0
  79. package/src/routes/_nav/monitoring/route.lazy.tsx +6 -6
  80. package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +2 -2
  81. package/src/routes/_nav/permissions/route.lazy.tsx +21 -311
  82. package/src/routes/_nav/permissions/route.tsx +1 -1
  83. package/src/routes/_nav/route.tsx +5 -13
  84. package/src/routes/_nav/sso/route.lazy.tsx +2 -3
  85. package/src/routes/_nav/users/$userId/route.lazy.tsx +91 -156
  86. package/src/routes/_nav/users/-components/users-table.tsx +1 -1
  87. package/src/routes/_nav/users/route.lazy.tsx +1 -1
  88. package/src/routes/login/route.lazy.tsx +1 -1
  89. package/src/routes/setup/route.lazy.tsx +2 -2
  90. package/src/server/__tests__/admin-billing.test.ts +191 -16
  91. package/src/server/__tests__/compliance.test.ts +44 -7
  92. package/src/server/__tests__/permissions.test.ts +10 -5
  93. package/src/server/__tests__/prompt-defaults.test.ts +3 -3
  94. package/src/server/admin-ai-alerts.ts +2 -1
  95. package/src/server/admin-ai-usage.ts +2 -1
  96. package/src/server/ai-memory/store.ts +6 -2
  97. package/src/server/{serverFns/ai-prompts → ai-prompts}/prompt-defaults.ts +5 -3
  98. package/src/server/{serverFns/dependency → dependency}/helpers.ts +4 -3
  99. package/src/server/knowledge-public/github-sync.ts +2 -1
  100. package/src/server/license-issue.ts +2 -1
  101. package/src/server/middlewares/auth-rate-limit.ts +117 -0
  102. package/src/server/observability/health-check.ts +4 -1
  103. package/src/server/observability/metrics.ts +17 -15
  104. package/src/server/observability/request-middleware.ts +2 -1
  105. package/src/server/observability/timing.ts +14 -16
  106. package/src/server/serverFns/admin-billing.ts +107 -12
  107. package/src/server/serverFns/ai-memory/list-users.ts +2 -1
  108. package/src/server/serverFns/ai-prompts/activate.ts +2 -1
  109. package/src/server/serverFns/ai-prompts/get.ts +3 -2
  110. package/src/server/serverFns/ai-prompts/list.ts +3 -2
  111. package/src/server/serverFns/ai-prompts/rollback.ts +3 -1
  112. package/src/server/serverFns/ai-prompts/save.ts +5 -3
  113. package/src/server/serverFns/ai-provider/create.ts +4 -1
  114. package/src/server/serverFns/ai-provider/delete.ts +4 -1
  115. package/src/server/serverFns/ai-provider/get.ts +4 -1
  116. package/src/server/serverFns/ai-provider/list.ts +28 -1
  117. package/src/server/serverFns/ai-provider/seed-from-seed.ts +2 -1
  118. package/src/server/serverFns/ai-provider/update.ts +4 -1
  119. package/src/server/serverFns/anyhub/market.ts +8 -1
  120. package/src/server/serverFns/audit.ts +14 -1
  121. package/src/server/serverFns/auth/setup.ts +3 -1
  122. package/src/server/serverFns/compliance.ts +32 -3
  123. package/src/server/serverFns/components/import.ts +69 -14
  124. package/src/server/serverFns/components/list.ts +4 -1
  125. package/src/server/serverFns/components/mutations.ts +9 -1
  126. package/src/server/serverFns/dependency/list.ts +28 -5
  127. package/src/server/serverFns/dependency/sync.ts +7 -2
  128. package/src/server/serverFns/dependency/update.ts +4 -1
  129. package/src/server/serverFns/developer-log-auto-generate.ts +63 -32
  130. package/src/server/serverFns/developer-logs.ts +5 -1
  131. package/src/server/serverFns/invitations.ts +7 -1
  132. package/src/server/serverFns/knowledge-public/bookmarks/create.ts +2 -1
  133. package/src/server/serverFns/knowledge-public/bookmarks/delete.ts +2 -1
  134. package/src/server/serverFns/knowledge-public/bookmarks/detail.ts +2 -1
  135. package/src/server/serverFns/knowledge-public/bookmarks/list.ts +2 -1
  136. package/src/server/serverFns/knowledge-public/bookmarks/sync-all-github.ts +2 -1
  137. package/src/server/serverFns/knowledge-public/bookmarks/update.ts +2 -1
  138. package/src/server/serverFns/knowledge-public/compliance/create.ts +2 -1
  139. package/src/server/serverFns/knowledge-public/compliance/delete.ts +2 -1
  140. package/src/server/serverFns/knowledge-public/compliance/detail.ts +2 -1
  141. package/src/server/serverFns/knowledge-public/compliance/list.ts +2 -1
  142. package/src/server/serverFns/knowledge-public/compliance/update.ts +2 -1
  143. package/src/server/serverFns/knowledge-public/legal/create.ts +2 -1
  144. package/src/server/serverFns/knowledge-public/legal/delete.ts +2 -1
  145. package/src/server/serverFns/knowledge-public/legal/detail.ts +2 -1
  146. package/src/server/serverFns/knowledge-public/legal/list.ts +2 -1
  147. package/src/server/serverFns/knowledge-public/legal/update.ts +2 -1
  148. package/src/server/serverFns/licenses.ts +8 -2
  149. package/src/server/serverFns/monitoring/get-errors.ts +2 -1
  150. package/src/server/serverFns/monitoring/get-health.ts +2 -1
  151. package/src/server/serverFns/monitoring/get-metrics.ts +2 -1
  152. package/src/server/serverFns/monitoring/get-request-logs.ts +2 -1
  153. package/src/server/serverFns/monitoring/report-error.ts +2 -1
  154. package/src/server/serverFns/monitoring/reset.ts +2 -1
  155. package/src/server/serverFns/oauth-providers.ts +4 -1
  156. package/src/server/serverFns/permissions.ts +18 -11
  157. package/src/server/serverFns/sentry/config.ts +11 -8
  158. package/src/server/serverFns/sso-config.ts +17 -2
  159. package/src/server/serverFns/user/create.ts +6 -1
  160. package/src/server/serverFns/user/delete.ts +6 -1
  161. package/src/server/serverFns/user/detail.ts +5 -2
  162. package/src/server/serverFns/user/list.ts +19 -4
  163. package/src/server/serverFns/user/reset-password.ts +10 -2
  164. package/src/server/serverFns/user/update-role.ts +10 -2
  165. package/src/server/serverFns/user/update-status.ts +10 -2
  166. package/src/styles/globals.css +4 -0
  167. package/src/components/data-table/data-table-pagination.tsx +0 -112
  168. package/src/components/data-table/data-table.tsx +0 -218
  169. package/src/components/data-table/table-detail-layout.tsx +0 -98
  170. package/src/components/ui/alert-dialog.tsx +0 -187
  171. package/src/components/ui/alert.tsx +0 -75
  172. package/src/components/ui/avatar.tsx +0 -106
  173. package/src/components/ui/badge.tsx +0 -51
  174. package/src/components/ui/button.tsx +0 -57
  175. package/src/components/ui/card.tsx +0 -102
  176. package/src/components/ui/checkbox.tsx +0 -28
  177. package/src/components/ui/collapsible.tsx +0 -19
  178. package/src/components/ui/dialog.tsx +0 -155
  179. package/src/components/ui/dropdown-menu.tsx +0 -267
  180. package/src/components/ui/field.tsx +0 -236
  181. package/src/components/ui/input-group.tsx +0 -158
  182. package/src/components/ui/input.tsx +0 -19
  183. package/src/components/ui/label.tsx +0 -17
  184. package/src/components/ui/pagination.tsx +0 -130
  185. package/src/components/ui/select.tsx +0 -234
  186. package/src/components/ui/separator.tsx +0 -22
  187. package/src/components/ui/sheet.tsx +0 -135
  188. package/src/components/ui/sidebar.tsx +0 -721
  189. package/src/components/ui/skeleton.tsx +0 -13
  190. package/src/components/ui/switch.tsx +0 -29
  191. package/src/components/ui/table.tsx +0 -115
  192. package/src/components/ui/textarea.tsx +0 -17
  193. package/src/components/ui/toast.tsx +0 -282
  194. package/src/components/ui/tooltip.tsx +0 -63
  195. package/src/hooks/use-mobile.ts +0 -19
  196. package/src/lib/avatar.ts +0 -41
  197. /package/src/routes/{api.auth.$.ts → api/auth/$.ts} +0 -0
  198. /package/src/routes/{api.sentry-test.ts → api/sentry-test.ts} +0 -0
@@ -1,155 +0,0 @@
1
- import * as React from "react"
2
- import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"
3
- import { cn } from "cn"
4
-
5
- import { Button } from "@/components/ui/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
- function DialogContent({
41
- className,
42
- children,
43
- showCloseButton = true,
44
- ...props
45
- }: DialogPrimitive.Popup.Props & {
46
- showCloseButton?: boolean
47
- }) {
48
- return (
49
- <DialogPortal>
50
- <DialogOverlay />
51
- <DialogPrimitive.Popup
52
- data-slot="dialog-content"
53
- className={cn(
54
- "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-6 rounded-xl bg-popover p-6 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-md 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",
55
- className
56
- )}
57
- {...props}
58
- >
59
- {children}
60
- {showCloseButton && (
61
- <DialogPrimitive.Close
62
- data-slot="dialog-close"
63
- render={
64
- <Button
65
- variant="ghost"
66
- className="absolute top-4 right-4"
67
- size="icon-sm"
68
- />
69
- }
70
- >
71
- <XIcon
72
- />
73
- <span className="sr-only">Close</span>
74
- </DialogPrimitive.Close>
75
- )}
76
- </DialogPrimitive.Popup>
77
- </DialogPortal>
78
- )
79
- }
80
-
81
- function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
82
- return (
83
- <div
84
- data-slot="dialog-header"
85
- className={cn("flex flex-col gap-2", className)}
86
- {...props}
87
- />
88
- )
89
- }
90
-
91
- function DialogFooter({
92
- className,
93
- showCloseButton = false,
94
- children,
95
- ...props
96
- }: React.ComponentProps<"div"> & {
97
- showCloseButton?: boolean
98
- }) {
99
- return (
100
- <div
101
- data-slot="dialog-footer"
102
- className={cn(
103
- "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
104
- className
105
- )}
106
- {...props}
107
- >
108
- {children}
109
- {showCloseButton && (
110
- <DialogPrimitive.Close render={<Button variant="outline" />}>
111
- Close
112
- </DialogPrimitive.Close>
113
- )}
114
- </div>
115
- )
116
- }
117
-
118
- function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
119
- return (
120
- <DialogPrimitive.Title
121
- data-slot="dialog-title"
122
- className={cn("font-heading leading-none font-medium", className)}
123
- {...props}
124
- />
125
- )
126
- }
127
-
128
- function DialogDescription({
129
- className,
130
- ...props
131
- }: DialogPrimitive.Description.Props) {
132
- return (
133
- <DialogPrimitive.Description
134
- data-slot="dialog-description"
135
- className={cn(
136
- "text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
137
- className
138
- )}
139
- {...props}
140
- />
141
- )
142
- }
143
-
144
- export {
145
- Dialog,
146
- DialogClose,
147
- DialogContent,
148
- DialogDescription,
149
- DialogFooter,
150
- DialogHeader,
151
- DialogOverlay,
152
- DialogPortal,
153
- DialogTitle,
154
- DialogTrigger,
155
- }
@@ -1,267 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { Menu as MenuPrimitive } from "@base-ui/react/menu"
5
- import { cn } from "cn"
6
- import { ChevronRightIcon, CheckIcon } from "lucide-react"
7
-
8
- function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
9
- return <MenuPrimitive.Root data-slot="dropdown-menu" {...props} />
10
- }
11
-
12
- function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
13
- return <MenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
14
- }
15
-
16
- function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
17
- return <MenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />
18
- }
19
-
20
- function DropdownMenuContent({
21
- align = "start",
22
- alignOffset = 0,
23
- side = "bottom",
24
- sideOffset = 4,
25
- className,
26
- ...props
27
- }: MenuPrimitive.Popup.Props &
28
- Pick<
29
- MenuPrimitive.Positioner.Props,
30
- "align" | "alignOffset" | "side" | "sideOffset"
31
- >) {
32
- return (
33
- <MenuPrimitive.Portal>
34
- <MenuPrimitive.Positioner
35
- className="isolate z-50 outline-none"
36
- align={align}
37
- alignOffset={alignOffset}
38
- side={side}
39
- sideOffset={sideOffset}
40
- >
41
- <MenuPrimitive.Popup
42
- data-slot="dropdown-menu-content"
43
- className={cn("z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-md 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 )}
44
- {...props}
45
- />
46
- </MenuPrimitive.Positioner>
47
- </MenuPrimitive.Portal>
48
- )
49
- }
50
-
51
- function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
52
- return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
53
- }
54
-
55
- function DropdownMenuLabel({
56
- className,
57
- inset,
58
- ...props
59
- }: MenuPrimitive.GroupLabel.Props & {
60
- inset?: boolean
61
- }) {
62
- return (
63
- <MenuPrimitive.GroupLabel
64
- data-slot="dropdown-menu-label"
65
- data-inset={inset}
66
- className={cn(
67
- "px-2 py-1.5 text-xs font-medium text-muted-foreground data-inset:pl-8",
68
- className
69
- )}
70
- {...props}
71
- />
72
- )
73
- }
74
-
75
- function DropdownMenuItem({
76
- className,
77
- inset,
78
- variant = "default",
79
- ...props
80
- }: MenuPrimitive.Item.Props & {
81
- inset?: boolean
82
- variant?: "default" | "destructive"
83
- }) {
84
- return (
85
- <MenuPrimitive.Item
86
- data-slot="dropdown-menu-item"
87
- data-inset={inset}
88
- data-variant={variant}
89
- className={cn(
90
- "group/dropdown-menu-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-8 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",
91
- className
92
- )}
93
- {...props}
94
- />
95
- )
96
- }
97
-
98
- function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {
99
- return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />
100
- }
101
-
102
- function DropdownMenuSubTrigger({
103
- className,
104
- inset,
105
- children,
106
- ...props
107
- }: MenuPrimitive.SubmenuTrigger.Props & {
108
- inset?: boolean
109
- }) {
110
- return (
111
- <MenuPrimitive.SubmenuTrigger
112
- data-slot="dropdown-menu-sub-trigger"
113
- data-inset={inset}
114
- className={cn(
115
- "flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-8 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",
116
- className
117
- )}
118
- {...props}
119
- >
120
- {children}
121
- <ChevronRightIcon className="ml-auto" />
122
- </MenuPrimitive.SubmenuTrigger>
123
- )
124
- }
125
-
126
- function DropdownMenuSubContent({
127
- align = "start",
128
- alignOffset = -3,
129
- side = "right",
130
- sideOffset = 0,
131
- className,
132
- ...props
133
- }: React.ComponentProps<typeof DropdownMenuContent>) {
134
- return (
135
- <DropdownMenuContent
136
- data-slot="dropdown-menu-sub-content"
137
- className={cn("w-auto min-w-[96px] rounded-md 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 )}
138
- align={align}
139
- alignOffset={alignOffset}
140
- side={side}
141
- sideOffset={sideOffset}
142
- {...props}
143
- />
144
- )
145
- }
146
-
147
- function DropdownMenuCheckboxItem({
148
- className,
149
- children,
150
- checked,
151
- inset,
152
- ...props
153
- }: MenuPrimitive.CheckboxItem.Props & {
154
- inset?: boolean
155
- }) {
156
- return (
157
- <MenuPrimitive.CheckboxItem
158
- data-slot="dropdown-menu-checkbox-item"
159
- data-inset={inset}
160
- className={cn(
161
- "relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-8 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
162
- className
163
- )}
164
- checked={checked}
165
- {...props}
166
- >
167
- <span
168
- className="pointer-events-none absolute right-2 flex items-center justify-center"
169
- data-slot="dropdown-menu-checkbox-item-indicator"
170
- >
171
- <MenuPrimitive.CheckboxItemIndicator>
172
- <CheckIcon
173
- />
174
- </MenuPrimitive.CheckboxItemIndicator>
175
- </span>
176
- {children}
177
- </MenuPrimitive.CheckboxItem>
178
- )
179
- }
180
-
181
- function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {
182
- return (
183
- <MenuPrimitive.RadioGroup
184
- data-slot="dropdown-menu-radio-group"
185
- {...props}
186
- />
187
- )
188
- }
189
-
190
- function DropdownMenuRadioItem({
191
- className,
192
- children,
193
- inset,
194
- ...props
195
- }: MenuPrimitive.RadioItem.Props & {
196
- inset?: boolean
197
- }) {
198
- return (
199
- <MenuPrimitive.RadioItem
200
- data-slot="dropdown-menu-radio-item"
201
- data-inset={inset}
202
- className={cn(
203
- "relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-8 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
204
- className
205
- )}
206
- {...props}
207
- >
208
- <span
209
- className="pointer-events-none absolute right-2 flex items-center justify-center"
210
- data-slot="dropdown-menu-radio-item-indicator"
211
- >
212
- <MenuPrimitive.RadioItemIndicator>
213
- <CheckIcon
214
- />
215
- </MenuPrimitive.RadioItemIndicator>
216
- </span>
217
- {children}
218
- </MenuPrimitive.RadioItem>
219
- )
220
- }
221
-
222
- function DropdownMenuSeparator({
223
- className,
224
- ...props
225
- }: MenuPrimitive.Separator.Props) {
226
- return (
227
- <MenuPrimitive.Separator
228
- data-slot="dropdown-menu-separator"
229
- className={cn("-mx-1 my-1 h-px bg-border", className)}
230
- {...props}
231
- />
232
- )
233
- }
234
-
235
- function DropdownMenuShortcut({
236
- className,
237
- ...props
238
- }: React.ComponentProps<"span">) {
239
- return (
240
- <span
241
- data-slot="dropdown-menu-shortcut"
242
- className={cn(
243
- "ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground",
244
- className
245
- )}
246
- {...props}
247
- />
248
- )
249
- }
250
-
251
- export {
252
- DropdownMenu,
253
- DropdownMenuPortal,
254
- DropdownMenuTrigger,
255
- DropdownMenuContent,
256
- DropdownMenuGroup,
257
- DropdownMenuLabel,
258
- DropdownMenuItem,
259
- DropdownMenuCheckboxItem,
260
- DropdownMenuRadioGroup,
261
- DropdownMenuRadioItem,
262
- DropdownMenuSeparator,
263
- DropdownMenuShortcut,
264
- DropdownMenuSub,
265
- DropdownMenuSubTrigger,
266
- DropdownMenuSubContent,
267
- }
@@ -1,236 +0,0 @@
1
- import { useMemo } from "react"
2
- import { cva, type VariantProps } from "class-variance-authority"
3
- import { cn } from "cn"
4
-
5
- import { Label } from "@/components/ui/label"
6
- import { Separator } from "@/components/ui/separator"
7
-
8
- function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {
9
- return (
10
- <fieldset
11
- data-slot="field-set"
12
- className={cn(
13
- "flex flex-col gap-6 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3",
14
- className
15
- )}
16
- {...props}
17
- />
18
- )
19
- }
20
-
21
- function FieldLegend({
22
- className,
23
- variant = "legend",
24
- ...props
25
- }: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) {
26
- return (
27
- <legend
28
- data-slot="field-legend"
29
- data-variant={variant}
30
- className={cn(
31
- "mb-3 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base",
32
- className
33
- )}
34
- {...props}
35
- />
36
- )
37
- }
38
-
39
- function FieldGroup({ className, ...props }: React.ComponentProps<"div">) {
40
- return (
41
- <div
42
- data-slot="field-group"
43
- className={cn(
44
- "group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4",
45
- className
46
- )}
47
- {...props}
48
- />
49
- )
50
- }
51
-
52
- const fieldVariants = cva(
53
- "group/field flex w-full gap-3 data-[invalid=true]:text-destructive",
54
- {
55
- variants: {
56
- orientation: {
57
- vertical: "flex-col *:w-full [&>.sr-only]:w-auto",
58
- horizontal:
59
- "flex-row items-center has-[>[data-slot=field-content]]:items-start *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
60
- responsive:
61
- "flex-col *:w-full @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:*:data-[slot=field-label]:flex-auto [&>.sr-only]:w-auto @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
62
- },
63
- },
64
- defaultVariants: {
65
- orientation: "vertical",
66
- },
67
- }
68
- )
69
-
70
- function Field({
71
- className,
72
- orientation = "vertical",
73
- ...props
74
- }: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) {
75
- return (
76
- <div
77
- role="group"
78
- data-slot="field"
79
- data-orientation={orientation}
80
- className={cn(fieldVariants({ orientation }), className)}
81
- {...props}
82
- />
83
- )
84
- }
85
-
86
- function FieldContent({ className, ...props }: React.ComponentProps<"div">) {
87
- return (
88
- <div
89
- data-slot="field-content"
90
- className={cn(
91
- "group/field-content flex flex-1 flex-col gap-1 leading-snug",
92
- className
93
- )}
94
- {...props}
95
- />
96
- )
97
- }
98
-
99
- function FieldLabel({
100
- className,
101
- ...props
102
- }: React.ComponentProps<typeof Label>) {
103
- return (
104
- <Label
105
- data-slot="field-label"
106
- className={cn(
107
- "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border has-[>[data-slot=field]]:not-has-[:disabled,[data-disabled]]:hover:bg-muted/50 has-[>[data-slot=field]]:has-[:focus-visible]:border-ring has-[>[data-slot=field]]:has-[:focus-visible]:ring-3 has-[>[data-slot=field]]:has-[:focus-visible]:ring-ring/50 *:data-[slot=field]:p-3 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10",
108
- "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col",
109
- className
110
- )}
111
- {...props}
112
- />
113
- )
114
- }
115
-
116
- function FieldTitle({ className, ...props }: React.ComponentProps<"div">) {
117
- return (
118
- <div
119
- data-slot="field-label"
120
- className={cn(
121
- "flex w-fit items-center gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50",
122
- className
123
- )}
124
- {...props}
125
- />
126
- )
127
- }
128
-
129
- function FieldDescription({ className, ...props }: React.ComponentProps<"p">) {
130
- return (
131
- <p
132
- data-slot="field-description"
133
- className={cn(
134
- "text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5",
135
- "last:mt-0 nth-last-2:-mt-1",
136
- "[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
137
- className
138
- )}
139
- {...props}
140
- />
141
- )
142
- }
143
-
144
- function FieldSeparator({
145
- children,
146
- className,
147
- ...props
148
- }: React.ComponentProps<"div"> & {
149
- children?: React.ReactNode
150
- }) {
151
- return (
152
- <div
153
- data-slot="field-separator"
154
- data-content={!!children}
155
- className={cn(
156
- "relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2",
157
- className
158
- )}
159
- {...props}
160
- >
161
- <Separator className="absolute inset-0 top-1/2" />
162
- {children && (
163
- <span
164
- className="relative mx-auto block w-fit bg-background px-2 text-muted-foreground"
165
- data-slot="field-separator-content"
166
- >
167
- {children}
168
- </span>
169
- )}
170
- </div>
171
- )
172
- }
173
-
174
- function FieldError({
175
- className,
176
- children,
177
- errors,
178
- ...props
179
- }: React.ComponentProps<"div"> & {
180
- errors?: Array<{ message?: string } | undefined>
181
- }) {
182
- const content = useMemo(() => {
183
- if (children) {
184
- return children
185
- }
186
-
187
- if (!errors?.length) {
188
- return null
189
- }
190
-
191
- const uniqueErrors = [
192
- ...new Map(errors.map((error) => [error?.message, error])).values(),
193
- ]
194
-
195
- if (uniqueErrors?.length == 1) {
196
- return uniqueErrors[0]?.message
197
- }
198
-
199
- return (
200
- <ul className="ml-4 flex list-disc flex-col gap-1">
201
- {uniqueErrors.map(
202
- (error, index) =>
203
- error?.message && <li key={index}>{error.message}</li>
204
- )}
205
- </ul>
206
- )
207
- }, [children, errors])
208
-
209
- if (!content) {
210
- return null
211
- }
212
-
213
- return (
214
- <div
215
- role="alert"
216
- data-slot="field-error"
217
- className={cn("text-sm font-normal text-destructive", className)}
218
- {...props}
219
- >
220
- {content}
221
- </div>
222
- )
223
- }
224
-
225
- export {
226
- Field,
227
- FieldLabel,
228
- FieldDescription,
229
- FieldError,
230
- FieldGroup,
231
- FieldLegend,
232
- FieldSeparator,
233
- FieldSet,
234
- FieldContent,
235
- FieldTitle,
236
- }