@allbluecn/admin-app 0.3.3 → 0.3.5

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 (109) hide show
  1. package/package.json +4 -3
  2. package/src/components/admin/admin-user-menu.tsx +4 -4
  3. package/src/components/admin/developer-log.tsx +7 -7
  4. package/src/components/ai-memory/memory-facts-panel.tsx +9 -9
  5. package/src/components/ai-prompts/preview-panel.tsx +1 -1
  6. package/src/components/ai-prompts/prompt-editor.tsx +8 -8
  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 +5 -5
  11. package/src/components/ai-provider/model-list-editor.tsx +2 -2
  12. package/src/components/ai-provider/provider-form.tsx +7 -7
  13. package/src/components/ai-provider/provider-table.tsx +6 -6
  14. package/src/components/auth/admin-login-form.tsx +6 -6
  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 +8 -8
  18. package/src/components/component/component-import-dialog.tsx +6 -6
  19. package/src/components/component/component-table.tsx +3 -3
  20. package/src/components/confirm-dialog.tsx +94 -0
  21. package/src/components/data-table/data-table-pagination.tsx +121 -0
  22. package/src/components/data-table/data-table.tsx +218 -0
  23. package/src/components/data-table/table-detail-layout.tsx +97 -0
  24. package/src/components/dependency/changelog-dialog.tsx +2 -2
  25. package/src/components/dependency/columns.tsx +3 -3
  26. package/src/components/dependency/dependency-table.tsx +7 -7
  27. package/src/components/dependency/edit-dialog.tsx +8 -8
  28. package/src/components/invitations/invitations-page.tsx +13 -13
  29. package/src/components/knowledge-public/bookmark-form-dialog.tsx +6 -6
  30. package/src/components/knowledge-public/compliance-form-dialog.tsx +6 -6
  31. package/src/components/knowledge-public/legal-form-dialog.tsx +7 -7
  32. package/src/components/layout/sidebar-02/app-sidebar.tsx +1 -1
  33. package/src/components/layout/sidebar-02/index.tsx +1 -1
  34. package/src/components/layout/sidebar-02/nav-main.tsx +2 -2
  35. package/src/components/layout/sidebar-02/nav-notifications.tsx +3 -3
  36. package/src/components/market/columns.tsx +4 -4
  37. package/src/components/market/market-app-form.tsx +6 -6
  38. package/src/components/market/market-app-list.tsx +4 -4
  39. package/src/components/monitoring/error-list.tsx +1 -1
  40. package/src/components/monitoring/metrics-stats.tsx +1 -1
  41. package/src/components/monitoring/request-log-table.tsx +1 -1
  42. package/src/components/notion-avatar.tsx +126 -0
  43. package/src/components/oauth-providers/provider-page.tsx +9 -9
  44. package/src/components/permissions/assign-dialog.tsx +5 -5
  45. package/src/components/permissions/create-role-dialog.tsx +6 -6
  46. package/src/components/ui/alert-dialog.tsx +185 -0
  47. package/src/components/ui/alert.tsx +75 -0
  48. package/src/components/ui/avatar.tsx +106 -0
  49. package/src/components/ui/badge.tsx +51 -0
  50. package/src/components/ui/button.tsx +57 -0
  51. package/src/components/ui/card.tsx +102 -0
  52. package/src/components/ui/checkbox.tsx +27 -0
  53. package/src/components/ui/collapsible.tsx +19 -0
  54. package/src/components/ui/dialog.tsx +155 -0
  55. package/src/components/ui/dropdown-menu.tsx +265 -0
  56. package/src/components/ui/field.tsx +236 -0
  57. package/src/components/ui/input-group.tsx +157 -0
  58. package/src/components/ui/input.tsx +19 -0
  59. package/src/components/ui/label.tsx +17 -0
  60. package/src/components/ui/pagination.tsx +130 -0
  61. package/src/components/ui/select.tsx +232 -0
  62. package/src/components/ui/separator.tsx +23 -0
  63. package/src/components/ui/sheet.tsx +134 -0
  64. package/src/components/ui/sidebar.tsx +721 -0
  65. package/src/components/ui/skeleton.tsx +13 -0
  66. package/src/components/ui/switch.tsx +30 -0
  67. package/src/components/ui/table.tsx +113 -0
  68. package/src/components/ui/textarea.tsx +17 -0
  69. package/src/components/ui/toast.tsx +308 -0
  70. package/src/components/ui/tooltip.tsx +64 -0
  71. package/src/components/user/columns.tsx +4 -4
  72. package/src/components/user/settings-activity-log.tsx +7 -7
  73. package/src/components/user/settings-profile/avatar-uploader.tsx +2 -2
  74. package/src/components/user/settings-profile/social-links.tsx +2 -2
  75. package/src/components/user/settings-profile.tsx +6 -6
  76. package/src/components/user/user-create-dialog.tsx +6 -6
  77. package/src/components/user/user-detail/error-boundary.tsx +1 -1
  78. package/src/components/user/user-detail/user-detail-dialogs.tsx +6 -6
  79. package/src/components/user/user-filters.tsx +3 -3
  80. package/src/components/user-avatar.tsx +82 -0
  81. package/src/hooks/use-mobile.ts +19 -0
  82. package/src/lib/datetime.ts +226 -0
  83. package/src/lib/sanitize.ts +18 -0
  84. package/src/providers/index.tsx +1 -1
  85. package/src/routes/__root.tsx +1 -1
  86. package/src/routes/_nav/audit/route.lazy.tsx +1 -1
  87. package/src/routes/_nav/compliance/route.lazy.tsx +3 -3
  88. package/src/routes/_nav/components/route.lazy.tsx +4 -4
  89. package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +6 -6
  90. package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +6 -6
  91. package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +6 -6
  92. package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +3 -3
  93. package/src/routes/_nav/licenses/new/route.lazy.tsx +5 -5
  94. package/src/routes/_nav/licenses/route.lazy.tsx +1 -1
  95. package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +2 -2
  96. package/src/routes/_nav/monitoring/errors/route.lazy.tsx +1 -1
  97. package/src/routes/_nav/monitoring/health/route.lazy.tsx +3 -3
  98. package/src/routes/_nav/monitoring/logs/route.lazy.tsx +3 -3
  99. package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +3 -3
  100. package/src/routes/_nav/monitoring/route.lazy.tsx +2 -2
  101. package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +1 -1
  102. package/src/routes/_nav/permissions/route.lazy.tsx +4 -4
  103. package/src/routes/_nav/sso/route.lazy.tsx +2 -2
  104. package/src/routes/_nav/users/$userId/route.lazy.tsx +8 -8
  105. package/src/routes/_nav/users/-components/users-table.tsx +1 -1
  106. package/src/routes/_nav/users/route.lazy.tsx +1 -1
  107. package/src/routes/setup/route.lazy.tsx +2 -2
  108. package/src/server/dependency/helpers.ts +0 -1
  109. package/src/styles/globals.css +3 -3
@@ -0,0 +1,51 @@
1
+ import { mergeProps } from "@base-ui/react/merge-props"
2
+ import { useRender } from "@base-ui/react/use-render"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+ import { cn } from "cn"
5
+
6
+ const badgeVariants = cva(
7
+ "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
12
+ secondary:
13
+ "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
14
+ destructive:
15
+ "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
16
+ outline:
17
+ "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
18
+ ghost:
19
+ "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
20
+ link: "text-primary underline-offset-4 hover:underline",
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ variant: "default",
25
+ },
26
+ }
27
+ )
28
+
29
+ function Badge({
30
+ className,
31
+ variant = "default",
32
+ render,
33
+ ...props
34
+ }: useRender.ComponentProps<"span"> & VariantProps<typeof badgeVariants>) {
35
+ return useRender({
36
+ defaultTagName: "span",
37
+ props: mergeProps<"span">(
38
+ {
39
+ className: cn(badgeVariants({ variant }), className),
40
+ },
41
+ props
42
+ ),
43
+ render,
44
+ state: {
45
+ slot: "badge",
46
+ variant,
47
+ },
48
+ })
49
+ }
50
+
51
+ export { Badge, badgeVariants }
@@ -0,0 +1,57 @@
1
+ import { Button as ButtonPrimitive } from "@base-ui/react/button"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { cn } from "cn"
4
+
5
+ const buttonVariants = cva(
6
+ "group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
7
+ {
8
+ variants: {
9
+ variant: {
10
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
11
+ outline:
12
+ "border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
13
+ secondary:
14
+ "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
15
+ ghost:
16
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
17
+ destructive:
18
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
19
+ link: "text-primary underline-offset-4 hover:underline",
20
+ },
21
+ size: {
22
+ default:
23
+ "h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
24
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
25
+ sm: "h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5",
26
+ lg: "h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
27
+ icon: "size-9",
28
+ "icon-xs":
29
+ "size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3",
30
+ "icon-sm":
31
+ "size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md",
32
+ "icon-lg": "size-10",
33
+ },
34
+ },
35
+ defaultVariants: {
36
+ variant: "default",
37
+ size: "default",
38
+ },
39
+ }
40
+ )
41
+
42
+ function Button({
43
+ className,
44
+ variant = "default",
45
+ size = "default",
46
+ ...props
47
+ }: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
48
+ return (
49
+ <ButtonPrimitive
50
+ data-slot="button"
51
+ className={cn(buttonVariants({ variant, size, className }))}
52
+ {...props}
53
+ />
54
+ )
55
+ }
56
+
57
+ export { Button, buttonVariants }
@@ -0,0 +1,102 @@
1
+ import * as React from "react"
2
+ import { cn } from "cn"
3
+
4
+ function Card({
5
+ className,
6
+ size = "default",
7
+ ...props
8
+ }: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
9
+ return (
10
+ <div
11
+ data-slot="card"
12
+ data-size={size}
13
+ className={cn(
14
+ "group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground shadow-xs ring-1 ring-foreground/10 [--card-spacing:--spacing(6)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
23
+ return (
24
+ <div
25
+ data-slot="card-header"
26
+ className={cn(
27
+ "group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
28
+ className
29
+ )}
30
+ {...props}
31
+ />
32
+ )
33
+ }
34
+
35
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
36
+ return (
37
+ <div
38
+ data-slot="card-title"
39
+ className={cn(
40
+ "font-heading text-base leading-normal font-medium group-data-[size=sm]/card:text-sm",
41
+ className
42
+ )}
43
+ {...props}
44
+ />
45
+ )
46
+ }
47
+
48
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
49
+ return (
50
+ <div
51
+ data-slot="card-description"
52
+ className={cn("text-sm text-muted-foreground", className)}
53
+ {...props}
54
+ />
55
+ )
56
+ }
57
+
58
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
59
+ return (
60
+ <div
61
+ data-slot="card-action"
62
+ className={cn(
63
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
64
+ className
65
+ )}
66
+ {...props}
67
+ />
68
+ )
69
+ }
70
+
71
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
72
+ return (
73
+ <div
74
+ data-slot="card-content"
75
+ className={cn("flex flex-col gap-3 px-(--card-spacing)", className)}
76
+ {...props}
77
+ />
78
+ )
79
+ }
80
+
81
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
82
+ return (
83
+ <div
84
+ data-slot="card-footer"
85
+ className={cn(
86
+ "flex items-center rounded-b-xl px-(--card-spacing) [.border-t]:pt-(--card-spacing)",
87
+ className
88
+ )}
89
+ {...props}
90
+ />
91
+ )
92
+ }
93
+
94
+ export {
95
+ Card,
96
+ CardHeader,
97
+ CardFooter,
98
+ CardTitle,
99
+ CardAction,
100
+ CardDescription,
101
+ CardContent,
102
+ }
@@ -0,0 +1,27 @@
1
+
2
+ import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
3
+ import { cn } from "cn"
4
+ import { CheckIcon } from "lucide-react"
5
+
6
+ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
7
+ return (
8
+ <CheckboxPrimitive.Root
9
+ data-slot="checkbox"
10
+ className={cn(
11
+ "peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input shadow-xs transition-shadow outline-none group-has-disabled/field:opacity-50 group-has-[:focus-visible]/field-label:ring-0 group-has-[:focus-visible]/field-label:not-data-checked:border-input after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground group-has-[:focus-visible]/field-label:data-checked:border-primary dark:data-checked:bg-primary",
12
+ className
13
+ )}
14
+ {...props}
15
+ >
16
+ <CheckboxPrimitive.Indicator
17
+ data-slot="checkbox-indicator"
18
+ className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
19
+ >
20
+ <CheckIcon
21
+ />
22
+ </CheckboxPrimitive.Indicator>
23
+ </CheckboxPrimitive.Root>
24
+ )
25
+ }
26
+
27
+ export { Checkbox }
@@ -0,0 +1,19 @@
1
+ import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible"
2
+
3
+ function Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {
4
+ return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
5
+ }
6
+
7
+ function CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {
8
+ return (
9
+ <CollapsiblePrimitive.Trigger data-slot="collapsible-trigger" {...props} />
10
+ )
11
+ }
12
+
13
+ function CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {
14
+ return (
15
+ <CollapsiblePrimitive.Panel data-slot="collapsible-content" {...props} />
16
+ )
17
+ }
18
+
19
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent }
@@ -0,0 +1,155 @@
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 "./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
+ }
@@ -0,0 +1,265 @@
1
+ import * as React from "react"
2
+ import { Menu as MenuPrimitive } from "@base-ui/react/menu"
3
+ import { cn } from "cn"
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-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 )}
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-2 py-1.5 text-xs font-medium text-muted-foreground data-inset:pl-8",
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-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",
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-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",
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-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 )}
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-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",
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-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",
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
+ }