Scrapboard.org client
1"use client";
2
3import * as React from "react";
4import { Command as CommandPrimitive } from "cmdk";
5import { SearchIcon } from "lucide-react";
6
7import { cn } from "@/lib/utils";
8import {
9 Dialog,
10 DialogContent,
11 DialogDescription,
12 DialogHeader,
13 DialogTitle,
14} from "@/components/ui/dialog";
15
16function Command({
17 className,
18 ...props
19}: React.ComponentProps<typeof CommandPrimitive>) {
20 return (
21 <CommandPrimitive
22 data-slot="command"
23 className={cn(
24 "bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
25 className
26 )}
27 {...props}
28 />
29 );
30}
31
32function CommandDialog({
33 title = "Command Palette",
34 description = "Search for a command to run...",
35 children,
36 className,
37 showCloseButton = true,
38 ...props
39}: React.ComponentProps<typeof Dialog> & {
40 title?: string;
41 description?: string;
42 className?: string;
43 showCloseButton?: boolean;
44}) {
45 return (
46 <Dialog {...props}>
47 <DialogHeader className="sr-only">
48 <DialogTitle>{title}</DialogTitle>
49 <DialogDescription>{description}</DialogDescription>
50 </DialogHeader>
51 <DialogContent
52 className={cn("overflow-hidden p-0", className)}
53 showCloseButton={showCloseButton}
54 >
55 <Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
56 {children}
57 </Command>
58 </DialogContent>
59 </Dialog>
60 );
61}
62
63function CommandInput({
64 className,
65 ...props
66}: React.ComponentProps<typeof CommandPrimitive.Input>) {
67 return (
68 <div
69 data-slot="command-input-wrapper"
70 className="flex h-9 items-center gap-2 border-b px-3"
71 >
72 <SearchIcon className="size-4 shrink-0 opacity-50" />
73 <CommandPrimitive.Input
74 data-slot="command-input"
75 className={cn(
76 "placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
77 className
78 )}
79 {...props}
80 />
81 </div>
82 );
83}
84
85function CommandList({
86 className,
87 ...props
88}: React.ComponentProps<typeof CommandPrimitive.List>) {
89 return (
90 <CommandPrimitive.List
91 data-slot="command-list"
92 className={cn(
93 "max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
94 className
95 )}
96 {...props}
97 />
98 );
99}
100
101function CommandEmpty({
102 ...props
103}: React.ComponentProps<typeof CommandPrimitive.Empty>) {
104 return (
105 <CommandPrimitive.Empty
106 data-slot="command-empty"
107 className="py-6 text-center text-sm"
108 {...props}
109 />
110 );
111}
112
113function CommandGroup({
114 className,
115 ...props
116}: React.ComponentProps<typeof CommandPrimitive.Group>) {
117 return (
118 <CommandPrimitive.Group
119 data-slot="command-group"
120 className={cn(
121 "text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
122 className
123 )}
124 {...props}
125 />
126 );
127}
128
129function CommandSeparator({
130 className,
131 ...props
132}: React.ComponentProps<typeof CommandPrimitive.Separator>) {
133 return (
134 <CommandPrimitive.Separator
135 data-slot="command-separator"
136 className={cn("bg-border -mx-1 h-px", className)}
137 {...props}
138 />
139 );
140}
141
142function CommandItem({
143 className,
144 ...props
145}: React.ComponentProps<typeof CommandPrimitive.Item>) {
146 return (
147 <CommandPrimitive.Item
148 data-slot="command-item"
149 className={cn(
150 "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
151 className
152 )}
153 {...props}
154 />
155 );
156}
157
158function CommandShortcut({
159 className,
160 ...props
161}: React.ComponentProps<"span">) {
162 return (
163 <span
164 data-slot="command-shortcut"
165 className={cn(
166 "text-muted-foreground ml-auto text-xs tracking-widest",
167 className
168 )}
169 {...props}
170 />
171 );
172}
173
174export {
175 Command,
176 CommandDialog,
177 CommandInput,
178 CommandList,
179 CommandEmpty,
180 CommandGroup,
181 CommandItem,
182 CommandShortcut,
183 CommandSeparator,
184};