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