@greatapps/greatchat-ui 0.1.5 → 0.2.0

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 (42) hide show
  1. package/dist/index.d.ts +106 -5
  2. package/dist/index.js +1787 -1116
  3. package/dist/index.js.map +1 -1
  4. package/package.json +17 -13
  5. package/src/components/channel-card.tsx +1 -1
  6. package/src/components/channel-create-dialog.tsx +126 -0
  7. package/src/components/channel-edit-dialog.tsx +132 -0
  8. package/src/components/channels-page.tsx +242 -0
  9. package/src/components/chat-dashboard.tsx +433 -0
  10. package/src/components/chat-input.tsx +1 -2
  11. package/src/components/chat-view.tsx +1 -8
  12. package/src/components/contact-avatar.tsx +1 -2
  13. package/src/components/contact-form-dialog.tsx +139 -0
  14. package/src/components/contact-info-panel.tsx +1 -4
  15. package/src/components/contacts-page.tsx +41 -0
  16. package/src/components/contacts-table.tsx +216 -0
  17. package/src/components/data-table.tsx +185 -0
  18. package/src/components/inbox-item.tsx +6 -4
  19. package/src/components/inbox-page.tsx +167 -0
  20. package/src/components/inbox-sidebar.tsx +1 -5
  21. package/src/components/message-bubble.tsx +4 -6
  22. package/src/components/new-conversation-dialog.tsx +2 -6
  23. package/src/components/whatsapp-icon.tsx +21 -0
  24. package/src/components/whatsapp-qr-dialog.tsx +147 -0
  25. package/src/components/whatsapp-status-badge.tsx +1 -1
  26. package/src/index.ts +37 -2
  27. package/src/components/ui/alert-dialog.tsx +0 -167
  28. package/src/components/ui/avatar.tsx +0 -51
  29. package/src/components/ui/badge.tsx +0 -44
  30. package/src/components/ui/button.tsx +0 -62
  31. package/src/components/ui/command.tsx +0 -106
  32. package/src/components/ui/dialog.tsx +0 -133
  33. package/src/components/ui/dropdown-menu.tsx +0 -173
  34. package/src/components/ui/input.tsx +0 -19
  35. package/src/components/ui/scroll-area.tsx +0 -50
  36. package/src/components/ui/select.tsx +0 -156
  37. package/src/components/ui/separator.tsx +0 -26
  38. package/src/components/ui/skeleton.tsx +0 -16
  39. package/src/components/ui/tabs.tsx +0 -64
  40. package/src/components/ui/textarea.tsx +0 -18
  41. package/src/components/ui/tooltip.tsx +0 -58
  42. package/src/lib/utils.ts +0 -6
@@ -0,0 +1,147 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState, useCallback } from "react";
4
+ import type { GchatHookConfig } from "../hooks/types";
5
+ import { useConnectChannel, useChannelQR, useChannelWhatsappStatus } from "../hooks/use-channels";
6
+ import {
7
+ Dialog,
8
+ DialogContent,
9
+ DialogHeader,
10
+ DialogTitle,
11
+ DialogDescription,
12
+ Button,
13
+ } from "@greatapps/greatauth-ui/ui";
14
+ import { Loader2, Check, AlertCircle, RefreshCw } from "lucide-react";
15
+ import { toast } from "sonner";
16
+
17
+ type QRState = "connecting" | "waiting_qr" | "showing_qr" | "connected" | "error";
18
+
19
+ export interface WhatsappQrDialogProps {
20
+ open: boolean;
21
+ onOpenChange: (open: boolean) => void;
22
+ channelId: number;
23
+ config: GchatHookConfig;
24
+ }
25
+
26
+ export function WhatsappQrDialog({
27
+ open,
28
+ onOpenChange,
29
+ channelId,
30
+ config,
31
+ }: WhatsappQrDialogProps) {
32
+ const connectChannel = useConnectChannel(config);
33
+ const [state, setState] = useState<QRState>("connecting");
34
+ const [errorMsg, setErrorMsg] = useState("");
35
+
36
+ const { data: qrUrl } = useChannelQR(
37
+ config,
38
+ channelId,
39
+ open && (state === "waiting_qr" || state === "showing_qr"),
40
+ );
41
+
42
+ const { data: status } = useChannelWhatsappStatus(
43
+ config,
44
+ channelId,
45
+ open && state !== "connected",
46
+ );
47
+
48
+ const startConnect = useCallback(() => {
49
+ setState("connecting");
50
+ setErrorMsg("");
51
+ connectChannel.mutate(channelId, {
52
+ onSuccess: () => setState("waiting_qr"),
53
+ onError: (err) => {
54
+ setState("error");
55
+ setErrorMsg(err.message || "Erro ao conectar");
56
+ },
57
+ });
58
+ }, [channelId, connectChannel]);
59
+
60
+ useEffect(() => {
61
+ if (!open) {
62
+ setState("connecting");
63
+ setErrorMsg("");
64
+ return;
65
+ }
66
+ startConnect();
67
+ // eslint-disable-next-line react-hooks/exhaustive-deps
68
+ }, [open, channelId]);
69
+
70
+ useEffect(() => {
71
+ if (qrUrl && (state === "waiting_qr" || state === "showing_qr")) {
72
+ setState("showing_qr");
73
+ }
74
+ }, [qrUrl, state]);
75
+
76
+ useEffect(() => {
77
+ if (status?.connected && status?.logged_in) {
78
+ setState("connected");
79
+ toast.success("WhatsApp conectado com sucesso!");
80
+ setTimeout(() => onOpenChange(false), 1500);
81
+ }
82
+ }, [status, onOpenChange]);
83
+
84
+ return (
85
+ <Dialog open={open} onOpenChange={onOpenChange}>
86
+ <DialogContent className="sm:max-w-md">
87
+ <DialogHeader>
88
+ <DialogTitle>Conectar WhatsApp</DialogTitle>
89
+ <DialogDescription>
90
+ Escaneie o QR code com seu WhatsApp para conectar
91
+ </DialogDescription>
92
+ </DialogHeader>
93
+
94
+ <div className="flex min-h-[300px] items-center justify-center">
95
+ {state === "connecting" && (
96
+ <div className="flex flex-col items-center gap-3 text-muted-foreground">
97
+ <Loader2 className="h-8 w-8 animate-spin" />
98
+ <p className="text-sm">Iniciando conexão...</p>
99
+ </div>
100
+ )}
101
+
102
+ {state === "waiting_qr" && (
103
+ <div className="flex flex-col items-center gap-3 text-muted-foreground">
104
+ <Loader2 className="h-8 w-8 animate-spin" />
105
+ <p className="text-sm">Gerando QR code...</p>
106
+ </div>
107
+ )}
108
+
109
+ {state === "showing_qr" && qrUrl && (
110
+ <div className="flex flex-col items-center gap-3">
111
+ <img
112
+ src={qrUrl}
113
+ alt="QR Code WhatsApp"
114
+ className="h-64 w-64 rounded-lg border"
115
+ />
116
+ <p className="text-sm text-muted-foreground">
117
+ Abra o WhatsApp &gt; Aparelhos conectados &gt; Conectar
118
+ </p>
119
+ </div>
120
+ )}
121
+
122
+ {state === "connected" && (
123
+ <div className="flex flex-col items-center gap-3 text-green-600">
124
+ <Check className="h-12 w-12" />
125
+ <p className="text-lg font-medium">Conectado!</p>
126
+ </div>
127
+ )}
128
+
129
+ {state === "error" && (
130
+ <div className="flex flex-col items-center gap-3 text-destructive">
131
+ <AlertCircle className="h-8 w-8" />
132
+ <p className="text-sm">{errorMsg || "Erro ao gerar QR code"}</p>
133
+ <Button
134
+ variant="outline"
135
+ size="sm"
136
+ onClick={startConnect}
137
+ >
138
+ <RefreshCw className="mr-2 h-4 w-4" />
139
+ Tentar novamente
140
+ </Button>
141
+ </div>
142
+ )}
143
+ </div>
144
+ </DialogContent>
145
+ </Dialog>
146
+ );
147
+ }
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import type { WhatsappStatus } from "../types";
4
- import { Badge } from "./ui/badge";
4
+ import { Badge } from "@greatapps/greatauth-ui/ui";
5
5
 
6
6
  export interface WhatsappStatusBadgeProps {
7
7
  status: WhatsappStatus | undefined | null;
package/src/index.ts CHANGED
@@ -15,13 +15,13 @@ export { createGchatClient } from "./client";
15
15
  export type { GchatClientConfig } from "./client";
16
16
 
17
17
  // Utils
18
- export { cn } from "./lib/utils";
18
+ export { cn } from "@greatapps/greatauth-ui/ui";
19
19
  export { groupMessagesByDate, formatDateGroup, formatMessageTime } from "./utils";
20
20
 
21
21
  // Hooks
22
22
  export * from "./hooks";
23
23
 
24
- // Components
24
+ // Base Components
25
25
  export {
26
26
  ChatView,
27
27
  ChatInput,
@@ -46,3 +46,38 @@ export type {
46
46
  ChannelCardProps,
47
47
  WhatsappStatusBadgeProps,
48
48
  } from "./components";
49
+
50
+ // Icons
51
+ export { WhatsappIcon } from "./components/whatsapp-icon";
52
+
53
+ // Dialogs & Forms
54
+ export { WhatsappQrDialog } from "./components/whatsapp-qr-dialog";
55
+ export type { WhatsappQrDialogProps } from "./components/whatsapp-qr-dialog";
56
+
57
+ export { ChannelCreateDialog } from "./components/channel-create-dialog";
58
+ export type { ChannelCreateDialogProps } from "./components/channel-create-dialog";
59
+
60
+ export { ChannelEditDialog } from "./components/channel-edit-dialog";
61
+ export type { ChannelEditDialogProps } from "./components/channel-edit-dialog";
62
+
63
+ export { ContactFormDialog } from "./components/contact-form-dialog";
64
+ export type { ContactFormDialogProps } from "./components/contact-form-dialog";
65
+
66
+ export { ContactsTable } from "./components/contacts-table";
67
+ export type { ContactsTableProps } from "./components/contacts-table";
68
+
69
+ export { DataTable } from "./components/data-table";
70
+ export type { DataTableProps } from "./components/data-table";
71
+
72
+ // Page Compositions
73
+ export { InboxPage } from "./components/inbox-page";
74
+ export type { InboxPageProps } from "./components/inbox-page";
75
+
76
+ export { ChannelsPage } from "./components/channels-page";
77
+ export type { ChannelsPageProps } from "./components/channels-page";
78
+
79
+ export { ContactsPage } from "./components/contacts-page";
80
+ export type { ContactsPageProps } from "./components/contacts-page";
81
+
82
+ export { ChatDashboard } from "./components/chat-dashboard";
83
+ export type { ChatDashboardProps } from "./components/chat-dashboard";
@@ -1,167 +0,0 @@
1
- import * as React from "react";
2
- import { AlertDialog as AlertDialogPrimitive } from "radix-ui";
3
-
4
- import { cn } from "../../lib/utils";
5
- import { Button } from "./button";
6
-
7
- function AlertDialog({
8
- ...props
9
- }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
10
- return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
11
- }
12
-
13
- function AlertDialogTrigger({
14
- ...props
15
- }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
16
- return (
17
- <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
18
- );
19
- }
20
-
21
- function AlertDialogPortal({
22
- ...props
23
- }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
24
- return (
25
- <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
26
- );
27
- }
28
-
29
- function AlertDialogOverlay({
30
- className,
31
- ...props
32
- }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
33
- return (
34
- <AlertDialogPrimitive.Overlay
35
- data-slot="alert-dialog-overlay"
36
- className={cn(
37
- "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 z-50",
38
- className,
39
- )}
40
- {...props}
41
- />
42
- );
43
- }
44
-
45
- function AlertDialogContent({
46
- className,
47
- ...props
48
- }: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
49
- return (
50
- <AlertDialogPortal>
51
- <AlertDialogOverlay />
52
- <AlertDialogPrimitive.Content
53
- data-slot="alert-dialog-content"
54
- className={cn(
55
- "data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-6 rounded-xl p-6 ring-1 duration-100 sm:max-w-lg fixed top-1/2 left-1/2 z-50 grid w-full max-w-xs -translate-x-1/2 -translate-y-1/2 outline-none",
56
- className,
57
- )}
58
- {...props}
59
- />
60
- </AlertDialogPortal>
61
- );
62
- }
63
-
64
- function AlertDialogHeader({
65
- className,
66
- ...props
67
- }: React.ComponentProps<"div">) {
68
- return (
69
- <div
70
- data-slot="alert-dialog-header"
71
- className={cn("grid gap-1.5 text-center sm:text-left", className)}
72
- {...props}
73
- />
74
- );
75
- }
76
-
77
- function AlertDialogFooter({
78
- className,
79
- ...props
80
- }: React.ComponentProps<"div">) {
81
- return (
82
- <div
83
- data-slot="alert-dialog-footer"
84
- className={cn(
85
- "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
86
- className,
87
- )}
88
- {...props}
89
- />
90
- );
91
- }
92
-
93
- function AlertDialogTitle({
94
- className,
95
- ...props
96
- }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
97
- return (
98
- <AlertDialogPrimitive.Title
99
- data-slot="alert-dialog-title"
100
- className={cn("text-lg font-medium", className)}
101
- {...props}
102
- />
103
- );
104
- }
105
-
106
- function AlertDialogDescription({
107
- className,
108
- ...props
109
- }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
110
- return (
111
- <AlertDialogPrimitive.Description
112
- data-slot="alert-dialog-description"
113
- className={cn("text-muted-foreground text-sm", className)}
114
- {...props}
115
- />
116
- );
117
- }
118
-
119
- function AlertDialogAction({
120
- className,
121
- variant = "default",
122
- size = "default",
123
- ...props
124
- }: React.ComponentProps<typeof AlertDialogPrimitive.Action> &
125
- Partial<Pick<React.ComponentProps<typeof Button>, "variant" | "size">>) {
126
- return (
127
- <Button variant={variant} size={size} asChild>
128
- <AlertDialogPrimitive.Action
129
- data-slot="alert-dialog-action"
130
- className={cn(className)}
131
- {...props}
132
- />
133
- </Button>
134
- );
135
- }
136
-
137
- function AlertDialogCancel({
138
- className,
139
- variant = "outline",
140
- size = "default",
141
- ...props
142
- }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel> &
143
- Partial<Pick<React.ComponentProps<typeof Button>, "variant" | "size">>) {
144
- return (
145
- <Button variant={variant} size={size} asChild>
146
- <AlertDialogPrimitive.Cancel
147
- data-slot="alert-dialog-cancel"
148
- className={cn(className)}
149
- {...props}
150
- />
151
- </Button>
152
- );
153
- }
154
-
155
- export {
156
- AlertDialog,
157
- AlertDialogAction,
158
- AlertDialogCancel,
159
- AlertDialogContent,
160
- AlertDialogDescription,
161
- AlertDialogFooter,
162
- AlertDialogHeader,
163
- AlertDialogOverlay,
164
- AlertDialogPortal,
165
- AlertDialogTitle,
166
- AlertDialogTrigger,
167
- };
@@ -1,51 +0,0 @@
1
- import * as React from "react";
2
- import { Avatar as AvatarPrimitive } from "radix-ui";
3
-
4
- import { cn } from "../../lib/utils";
5
-
6
- function Avatar({
7
- className,
8
- ...props
9
- }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
10
- return (
11
- <AvatarPrimitive.Root
12
- data-slot="avatar"
13
- className={cn(
14
- "relative flex size-8 shrink-0 overflow-hidden rounded-full",
15
- className,
16
- )}
17
- {...props}
18
- />
19
- );
20
- }
21
-
22
- function AvatarImage({
23
- className,
24
- ...props
25
- }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
26
- return (
27
- <AvatarPrimitive.Image
28
- data-slot="avatar-image"
29
- className={cn("aspect-square size-full", className)}
30
- {...props}
31
- />
32
- );
33
- }
34
-
35
- function AvatarFallback({
36
- className,
37
- ...props
38
- }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
39
- return (
40
- <AvatarPrimitive.Fallback
41
- data-slot="avatar-fallback"
42
- className={cn(
43
- "flex size-full items-center justify-center rounded-full bg-muted",
44
- className,
45
- )}
46
- {...props}
47
- />
48
- );
49
- }
50
-
51
- export { Avatar, AvatarImage, AvatarFallback };
@@ -1,44 +0,0 @@
1
- import * as React from "react";
2
- import { cva, type VariantProps } from "class-variance-authority";
3
- import { Slot } from "radix-ui";
4
-
5
- import { cn } from "../../lib/utils";
6
-
7
- const badgeVariants = cva(
8
- "h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none overflow-hidden",
9
- {
10
- variants: {
11
- variant: {
12
- default: "bg-primary text-primary-foreground",
13
- secondary: "bg-secondary text-secondary-foreground",
14
- destructive:
15
- "bg-destructive/10 text-destructive dark:bg-destructive/20",
16
- outline: "border-border text-foreground",
17
- ghost: "hover:bg-muted hover:text-muted-foreground",
18
- },
19
- },
20
- defaultVariants: {
21
- variant: "default",
22
- },
23
- },
24
- );
25
-
26
- function Badge({
27
- className,
28
- variant = "default",
29
- asChild = false,
30
- ...props
31
- }: React.ComponentProps<"span"> &
32
- VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
33
- const Comp = asChild ? Slot.Root : "span";
34
-
35
- return (
36
- <Comp
37
- data-slot="badge"
38
- className={cn(badgeVariants({ variant }), className)}
39
- {...props}
40
- />
41
- );
42
- }
43
-
44
- export { Badge, badgeVariants };
@@ -1,62 +0,0 @@
1
- import * as React from "react";
2
- import { cva, type VariantProps } from "class-variance-authority";
3
- import { Slot } from "radix-ui";
4
-
5
- import { cn } from "../../lib/utils";
6
-
7
- const buttonVariants = cva(
8
- "focus-visible:border-ring focus-visible:ring-ring/50 rounded-md border border-transparent text-sm font-medium focus-visible:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none select-none",
9
- {
10
- variants: {
11
- variant: {
12
- default: "bg-primary text-primary-foreground hover:bg-primary/80",
13
- outline:
14
- "border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 shadow-xs",
15
- secondary:
16
- "bg-secondary text-secondary-foreground hover:bg-secondary/80",
17
- ghost:
18
- "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50",
19
- destructive:
20
- "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:bg-destructive/20 text-destructive",
21
- link: "text-primary underline-offset-4 hover:underline",
22
- },
23
- size: {
24
- default: "h-9 gap-1.5 px-2.5",
25
- xs: "h-6 gap-1 px-2 text-xs [&_svg:not([class*='size-'])]:size-3",
26
- sm: "h-8 gap-1 px-2.5",
27
- lg: "h-10 gap-1.5 px-2.5",
28
- icon: "size-9",
29
- "icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
30
- "icon-sm": "size-8",
31
- "icon-lg": "size-10",
32
- },
33
- },
34
- defaultVariants: {
35
- variant: "default",
36
- size: "default",
37
- },
38
- },
39
- );
40
-
41
- function Button({
42
- className,
43
- variant = "default",
44
- size = "default",
45
- asChild = false,
46
- ...props
47
- }: React.ComponentProps<"button"> &
48
- VariantProps<typeof buttonVariants> & {
49
- asChild?: boolean;
50
- }) {
51
- const Comp = asChild ? Slot.Root : "button";
52
-
53
- return (
54
- <Comp
55
- data-slot="button"
56
- className={cn(buttonVariants({ variant, size, className }))}
57
- {...props}
58
- />
59
- );
60
- }
61
-
62
- export { Button, buttonVariants };
@@ -1,106 +0,0 @@
1
- import * as React from "react";
2
- import { Command as CommandPrimitive } from "cmdk";
3
- import { Search } from "lucide-react";
4
-
5
- import { cn } from "../../lib/utils";
6
-
7
- function Command({
8
- className,
9
- ...props
10
- }: React.ComponentProps<typeof CommandPrimitive>) {
11
- return (
12
- <CommandPrimitive
13
- data-slot="command"
14
- className={cn(
15
- "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
16
- className,
17
- )}
18
- {...props}
19
- />
20
- );
21
- }
22
-
23
- function CommandInput({
24
- className,
25
- ...props
26
- }: React.ComponentProps<typeof CommandPrimitive.Input>) {
27
- return (
28
- <div className="flex h-9 items-center gap-2 border-b px-3" data-slot="command-input-wrapper">
29
- <Search className="size-4 shrink-0 opacity-50" />
30
- <CommandPrimitive.Input
31
- data-slot="command-input"
32
- className={cn(
33
- "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
34
- className,
35
- )}
36
- {...props}
37
- />
38
- </div>
39
- );
40
- }
41
-
42
- function CommandList({
43
- className,
44
- ...props
45
- }: React.ComponentProps<typeof CommandPrimitive.List>) {
46
- return (
47
- <CommandPrimitive.List
48
- data-slot="command-list"
49
- className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
50
- {...props}
51
- />
52
- );
53
- }
54
-
55
- function CommandEmpty({
56
- ...props
57
- }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
58
- return (
59
- <CommandPrimitive.Empty
60
- data-slot="command-empty"
61
- className="py-6 text-center text-sm"
62
- {...props}
63
- />
64
- );
65
- }
66
-
67
- function CommandGroup({
68
- className,
69
- ...props
70
- }: React.ComponentProps<typeof CommandPrimitive.Group>) {
71
- return (
72
- <CommandPrimitive.Group
73
- data-slot="command-group"
74
- className={cn(
75
- "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
76
- className,
77
- )}
78
- {...props}
79
- />
80
- );
81
- }
82
-
83
- function CommandItem({
84
- className,
85
- ...props
86
- }: React.ComponentProps<typeof CommandPrimitive.Item>) {
87
- return (
88
- <CommandPrimitive.Item
89
- data-slot="command-item"
90
- className={cn(
91
- "relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
92
- className,
93
- )}
94
- {...props}
95
- />
96
- );
97
- }
98
-
99
- export {
100
- Command,
101
- CommandInput,
102
- CommandList,
103
- CommandEmpty,
104
- CommandGroup,
105
- CommandItem,
106
- };