@gmickel/gno 0.3.4 → 0.4.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 (57) hide show
  1. package/README.md +194 -53
  2. package/assets/badges/license.svg +12 -0
  3. package/assets/badges/npm.svg +13 -0
  4. package/assets/badges/twitter.svg +22 -0
  5. package/assets/badges/website.svg +22 -0
  6. package/package.json +30 -1
  7. package/src/cli/commands/ask.ts +11 -186
  8. package/src/cli/commands/models/pull.ts +9 -4
  9. package/src/cli/commands/serve.ts +19 -0
  10. package/src/cli/program.ts +28 -0
  11. package/src/llm/registry.ts +3 -1
  12. package/src/pipeline/answer.ts +191 -0
  13. package/src/serve/CLAUDE.md +91 -0
  14. package/src/serve/bunfig.toml +2 -0
  15. package/src/serve/context.ts +181 -0
  16. package/src/serve/index.ts +7 -0
  17. package/src/serve/public/app.tsx +56 -0
  18. package/src/serve/public/components/ai-elements/code-block.tsx +176 -0
  19. package/src/serve/public/components/ai-elements/conversation.tsx +98 -0
  20. package/src/serve/public/components/ai-elements/inline-citation.tsx +285 -0
  21. package/src/serve/public/components/ai-elements/loader.tsx +96 -0
  22. package/src/serve/public/components/ai-elements/message.tsx +443 -0
  23. package/src/serve/public/components/ai-elements/prompt-input.tsx +1421 -0
  24. package/src/serve/public/components/ai-elements/sources.tsx +75 -0
  25. package/src/serve/public/components/ai-elements/suggestion.tsx +51 -0
  26. package/src/serve/public/components/preset-selector.tsx +403 -0
  27. package/src/serve/public/components/ui/badge.tsx +46 -0
  28. package/src/serve/public/components/ui/button-group.tsx +82 -0
  29. package/src/serve/public/components/ui/button.tsx +62 -0
  30. package/src/serve/public/components/ui/card.tsx +92 -0
  31. package/src/serve/public/components/ui/carousel.tsx +244 -0
  32. package/src/serve/public/components/ui/collapsible.tsx +31 -0
  33. package/src/serve/public/components/ui/command.tsx +181 -0
  34. package/src/serve/public/components/ui/dialog.tsx +141 -0
  35. package/src/serve/public/components/ui/dropdown-menu.tsx +255 -0
  36. package/src/serve/public/components/ui/hover-card.tsx +42 -0
  37. package/src/serve/public/components/ui/input-group.tsx +167 -0
  38. package/src/serve/public/components/ui/input.tsx +21 -0
  39. package/src/serve/public/components/ui/progress.tsx +28 -0
  40. package/src/serve/public/components/ui/scroll-area.tsx +56 -0
  41. package/src/serve/public/components/ui/select.tsx +188 -0
  42. package/src/serve/public/components/ui/separator.tsx +26 -0
  43. package/src/serve/public/components/ui/table.tsx +114 -0
  44. package/src/serve/public/components/ui/textarea.tsx +18 -0
  45. package/src/serve/public/components/ui/tooltip.tsx +59 -0
  46. package/src/serve/public/globals.css +226 -0
  47. package/src/serve/public/hooks/use-api.ts +112 -0
  48. package/src/serve/public/index.html +13 -0
  49. package/src/serve/public/pages/Ask.tsx +442 -0
  50. package/src/serve/public/pages/Browse.tsx +270 -0
  51. package/src/serve/public/pages/Dashboard.tsx +202 -0
  52. package/src/serve/public/pages/DocView.tsx +302 -0
  53. package/src/serve/public/pages/Search.tsx +335 -0
  54. package/src/serve/routes/api.ts +763 -0
  55. package/src/serve/server.ts +249 -0
  56. package/src/store/sqlite/adapter.ts +47 -0
  57. package/src/store/types.ts +10 -0
@@ -0,0 +1,62 @@
1
+ import { Slot } from '@radix-ui/react-slot';
2
+ import { cva, type VariantProps } from 'class-variance-authority';
3
+ import type * as React from 'react';
4
+
5
+ import { cn } from '../../lib/utils';
6
+
7
+ const buttonVariants = cva(
8
+ "inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: 'bg-primary text-primary-foreground hover:bg-primary/90',
13
+ destructive:
14
+ 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40',
15
+ outline:
16
+ 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50',
17
+ secondary:
18
+ 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
19
+ ghost:
20
+ 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
21
+ link: 'text-primary underline-offset-4 hover:underline',
22
+ },
23
+ size: {
24
+ default: 'h-9 px-4 py-2 has-[>svg]:px-3',
25
+ sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5',
26
+ lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
27
+ icon: 'size-9',
28
+ 'icon-sm': 'size-8',
29
+ 'icon-lg': 'size-10',
30
+ },
31
+ },
32
+ defaultVariants: {
33
+ variant: 'default',
34
+ size: 'default',
35
+ },
36
+ }
37
+ );
38
+
39
+ function Button({
40
+ className,
41
+ variant = 'default',
42
+ size = 'default',
43
+ asChild = false,
44
+ ...props
45
+ }: React.ComponentProps<'button'> &
46
+ VariantProps<typeof buttonVariants> & {
47
+ asChild?: boolean;
48
+ }) {
49
+ const Comp = asChild ? Slot : 'button';
50
+
51
+ return (
52
+ <Comp
53
+ className={cn(buttonVariants({ variant, size, className }))}
54
+ data-size={size}
55
+ data-slot="button"
56
+ data-variant={variant}
57
+ {...props}
58
+ />
59
+ );
60
+ }
61
+
62
+ export { Button, buttonVariants };
@@ -0,0 +1,92 @@
1
+ import type * as React from 'react';
2
+
3
+ import { cn } from '../../lib/utils';
4
+
5
+ function Card({ className, ...props }: React.ComponentProps<'div'>) {
6
+ return (
7
+ <div
8
+ className={cn(
9
+ 'flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm',
10
+ className
11
+ )}
12
+ data-slot="card"
13
+ {...props}
14
+ />
15
+ );
16
+ }
17
+
18
+ function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
19
+ return (
20
+ <div
21
+ className={cn(
22
+ '@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
23
+ className
24
+ )}
25
+ data-slot="card-header"
26
+ {...props}
27
+ />
28
+ );
29
+ }
30
+
31
+ function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
32
+ return (
33
+ <div
34
+ className={cn('font-semibold leading-none', className)}
35
+ data-slot="card-title"
36
+ {...props}
37
+ />
38
+ );
39
+ }
40
+
41
+ function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
42
+ return (
43
+ <div
44
+ className={cn('text-muted-foreground text-sm', className)}
45
+ data-slot="card-description"
46
+ {...props}
47
+ />
48
+ );
49
+ }
50
+
51
+ function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
52
+ return (
53
+ <div
54
+ className={cn(
55
+ 'col-start-2 row-span-2 row-start-1 self-start justify-self-end',
56
+ className
57
+ )}
58
+ data-slot="card-action"
59
+ {...props}
60
+ />
61
+ );
62
+ }
63
+
64
+ function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
65
+ return (
66
+ <div
67
+ className={cn('px-6', className)}
68
+ data-slot="card-content"
69
+ {...props}
70
+ />
71
+ );
72
+ }
73
+
74
+ function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
75
+ return (
76
+ <div
77
+ className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
78
+ data-slot="card-footer"
79
+ {...props}
80
+ />
81
+ );
82
+ }
83
+
84
+ export {
85
+ Card,
86
+ CardHeader,
87
+ CardFooter,
88
+ CardTitle,
89
+ CardAction,
90
+ CardDescription,
91
+ CardContent,
92
+ };
@@ -0,0 +1,244 @@
1
+ import useEmblaCarousel, {
2
+ type UseEmblaCarouselType,
3
+ } from 'embla-carousel-react';
4
+ import { ArrowLeft, ArrowRight } from 'lucide-react';
5
+ import * as React from 'react';
6
+ import { cn } from '../../lib/utils';
7
+ import { Button } from './button';
8
+
9
+ type CarouselApi = UseEmblaCarouselType[1];
10
+ type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
11
+ type CarouselOptions = UseCarouselParameters[0];
12
+ type CarouselPlugin = UseCarouselParameters[1];
13
+
14
+ interface CarouselProps {
15
+ opts?: CarouselOptions;
16
+ plugins?: CarouselPlugin;
17
+ orientation?: 'horizontal' | 'vertical';
18
+ setApi?: (api: CarouselApi) => void;
19
+ }
20
+
21
+ type CarouselContextProps = {
22
+ carouselRef: ReturnType<typeof useEmblaCarousel>[0];
23
+ api: ReturnType<typeof useEmblaCarousel>[1];
24
+ scrollPrev: () => void;
25
+ scrollNext: () => void;
26
+ canScrollPrev: boolean;
27
+ canScrollNext: boolean;
28
+ } & CarouselProps;
29
+
30
+ const CarouselContext = React.createContext<CarouselContextProps | null>(null);
31
+
32
+ function useCarousel() {
33
+ const context = React.useContext(CarouselContext);
34
+
35
+ if (!context) {
36
+ throw new Error('useCarousel must be used within a <Carousel />');
37
+ }
38
+
39
+ return context;
40
+ }
41
+
42
+ function Carousel({
43
+ orientation = 'horizontal',
44
+ opts,
45
+ setApi,
46
+ plugins,
47
+ className,
48
+ children,
49
+ ...props
50
+ }: React.ComponentProps<'div'> & CarouselProps) {
51
+ const [carouselRef, api] = useEmblaCarousel(
52
+ {
53
+ ...opts,
54
+ axis: orientation === 'horizontal' ? 'x' : 'y',
55
+ },
56
+ plugins
57
+ );
58
+ const [canScrollPrev, setCanScrollPrev] = React.useState(false);
59
+ const [canScrollNext, setCanScrollNext] = React.useState(false);
60
+
61
+ const onSelect = React.useCallback((api: CarouselApi) => {
62
+ if (!api) {
63
+ return;
64
+ }
65
+ setCanScrollPrev(api.canScrollPrev());
66
+ setCanScrollNext(api.canScrollNext());
67
+ }, []);
68
+
69
+ const scrollPrev = React.useCallback(() => {
70
+ api?.scrollPrev();
71
+ }, [api]);
72
+
73
+ const scrollNext = React.useCallback(() => {
74
+ api?.scrollNext();
75
+ }, [api]);
76
+
77
+ const handleKeyDown = React.useCallback(
78
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
79
+ if (event.key === 'ArrowLeft') {
80
+ event.preventDefault();
81
+ scrollPrev();
82
+ } else if (event.key === 'ArrowRight') {
83
+ event.preventDefault();
84
+ scrollNext();
85
+ }
86
+ },
87
+ [scrollPrev, scrollNext]
88
+ );
89
+
90
+ React.useEffect(() => {
91
+ if (!(api && setApi)) {
92
+ return;
93
+ }
94
+ setApi(api);
95
+ }, [api, setApi]);
96
+
97
+ React.useEffect(() => {
98
+ if (!api) {
99
+ return;
100
+ }
101
+ onSelect(api);
102
+ api.on('reInit', onSelect);
103
+ api.on('select', onSelect);
104
+
105
+ return () => {
106
+ api?.off('select', onSelect);
107
+ };
108
+ }, [api, onSelect]);
109
+
110
+ return (
111
+ <CarouselContext.Provider
112
+ value={{
113
+ carouselRef,
114
+ api,
115
+ opts,
116
+ orientation:
117
+ orientation || (opts?.axis === 'y' ? 'vertical' : 'horizontal'),
118
+ scrollPrev,
119
+ scrollNext,
120
+ canScrollPrev,
121
+ canScrollNext,
122
+ }}
123
+ >
124
+ <div
125
+ aria-roledescription="carousel"
126
+ className={cn('relative', className)}
127
+ data-slot="carousel"
128
+ onKeyDownCapture={handleKeyDown}
129
+ role="region"
130
+ {...props}
131
+ >
132
+ {children}
133
+ </div>
134
+ </CarouselContext.Provider>
135
+ );
136
+ }
137
+
138
+ function CarouselContent({ className, ...props }: React.ComponentProps<'div'>) {
139
+ const { carouselRef, orientation } = useCarousel();
140
+
141
+ return (
142
+ <div
143
+ className="overflow-hidden"
144
+ data-slot="carousel-content"
145
+ ref={carouselRef}
146
+ >
147
+ <div
148
+ className={cn(
149
+ 'flex',
150
+ orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',
151
+ className
152
+ )}
153
+ {...props}
154
+ />
155
+ </div>
156
+ );
157
+ }
158
+
159
+ function CarouselItem({ className, ...props }: React.ComponentProps<'div'>) {
160
+ const { orientation } = useCarousel();
161
+
162
+ return (
163
+ <div
164
+ aria-roledescription="slide"
165
+ className={cn(
166
+ 'min-w-0 shrink-0 grow-0 basis-full',
167
+ orientation === 'horizontal' ? 'pl-4' : 'pt-4',
168
+ className
169
+ )}
170
+ data-slot="carousel-item"
171
+ role="group"
172
+ {...props}
173
+ />
174
+ );
175
+ }
176
+
177
+ function CarouselPrevious({
178
+ className,
179
+ variant = 'outline',
180
+ size = 'icon',
181
+ ...props
182
+ }: React.ComponentProps<typeof Button>) {
183
+ const { orientation, scrollPrev, canScrollPrev } = useCarousel();
184
+
185
+ return (
186
+ <Button
187
+ className={cn(
188
+ 'absolute size-8 rounded-full',
189
+ orientation === 'horizontal'
190
+ ? 'top-1/2 -left-12 -translate-y-1/2'
191
+ : '-top-12 left-1/2 -translate-x-1/2 rotate-90',
192
+ className
193
+ )}
194
+ data-slot="carousel-previous"
195
+ disabled={!canScrollPrev}
196
+ onClick={scrollPrev}
197
+ size={size}
198
+ variant={variant}
199
+ {...props}
200
+ >
201
+ <ArrowLeft />
202
+ <span className="sr-only">Previous slide</span>
203
+ </Button>
204
+ );
205
+ }
206
+
207
+ function CarouselNext({
208
+ className,
209
+ variant = 'outline',
210
+ size = 'icon',
211
+ ...props
212
+ }: React.ComponentProps<typeof Button>) {
213
+ const { orientation, scrollNext, canScrollNext } = useCarousel();
214
+
215
+ return (
216
+ <Button
217
+ className={cn(
218
+ 'absolute size-8 rounded-full',
219
+ orientation === 'horizontal'
220
+ ? 'top-1/2 -right-12 -translate-y-1/2'
221
+ : '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',
222
+ className
223
+ )}
224
+ data-slot="carousel-next"
225
+ disabled={!canScrollNext}
226
+ onClick={scrollNext}
227
+ size={size}
228
+ variant={variant}
229
+ {...props}
230
+ >
231
+ <ArrowRight />
232
+ <span className="sr-only">Next slide</span>
233
+ </Button>
234
+ );
235
+ }
236
+
237
+ export {
238
+ type CarouselApi,
239
+ Carousel,
240
+ CarouselContent,
241
+ CarouselItem,
242
+ CarouselPrevious,
243
+ CarouselNext,
244
+ };
@@ -0,0 +1,31 @@
1
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
2
+
3
+ function Collapsible({
4
+ ...props
5
+ }: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
6
+ return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />;
7
+ }
8
+
9
+ function CollapsibleTrigger({
10
+ ...props
11
+ }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
12
+ return (
13
+ <CollapsiblePrimitive.CollapsibleTrigger
14
+ data-slot="collapsible-trigger"
15
+ {...props}
16
+ />
17
+ );
18
+ }
19
+
20
+ function CollapsibleContent({
21
+ ...props
22
+ }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
23
+ return (
24
+ <CollapsiblePrimitive.CollapsibleContent
25
+ data-slot="collapsible-content"
26
+ {...props}
27
+ />
28
+ );
29
+ }
30
+
31
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent };
@@ -0,0 +1,181 @@
1
+ import { Command as CommandPrimitive } from 'cmdk';
2
+ import { SearchIcon } from 'lucide-react';
3
+ import type * as React from 'react';
4
+ import { cn } from '../../lib/utils';
5
+ import {
6
+ Dialog,
7
+ DialogContent,
8
+ DialogDescription,
9
+ DialogHeader,
10
+ DialogTitle,
11
+ } from './dialog';
12
+
13
+ function Command({
14
+ className,
15
+ ...props
16
+ }: React.ComponentProps<typeof CommandPrimitive>) {
17
+ return (
18
+ <CommandPrimitive
19
+ className={cn(
20
+ 'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
21
+ className
22
+ )}
23
+ data-slot="command"
24
+ {...props}
25
+ />
26
+ );
27
+ }
28
+
29
+ function CommandDialog({
30
+ title = 'Command Palette',
31
+ description = 'Search for a command to run...',
32
+ children,
33
+ className,
34
+ showCloseButton = true,
35
+ ...props
36
+ }: React.ComponentProps<typeof Dialog> & {
37
+ title?: string;
38
+ description?: string;
39
+ className?: string;
40
+ showCloseButton?: boolean;
41
+ }) {
42
+ return (
43
+ <Dialog {...props}>
44
+ <DialogHeader className="sr-only">
45
+ <DialogTitle>{title}</DialogTitle>
46
+ <DialogDescription>{description}</DialogDescription>
47
+ </DialogHeader>
48
+ <DialogContent
49
+ className={cn('overflow-hidden p-0', className)}
50
+ showCloseButton={showCloseButton}
51
+ >
52
+ <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]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[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">
53
+ {children}
54
+ </Command>
55
+ </DialogContent>
56
+ </Dialog>
57
+ );
58
+ }
59
+
60
+ function CommandInput({
61
+ className,
62
+ ...props
63
+ }: React.ComponentProps<typeof CommandPrimitive.Input>) {
64
+ return (
65
+ <div
66
+ className="flex h-9 items-center gap-2 border-b px-3"
67
+ data-slot="command-input-wrapper"
68
+ >
69
+ <SearchIcon className="size-4 shrink-0 opacity-50" />
70
+ <CommandPrimitive.Input
71
+ className={cn(
72
+ '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',
73
+ className
74
+ )}
75
+ data-slot="command-input"
76
+ {...props}
77
+ />
78
+ </div>
79
+ );
80
+ }
81
+
82
+ function CommandList({
83
+ className,
84
+ ...props
85
+ }: React.ComponentProps<typeof CommandPrimitive.List>) {
86
+ return (
87
+ <CommandPrimitive.List
88
+ className={cn(
89
+ 'max-h-[300px] scroll-py-1 overflow-y-auto overflow-x-hidden',
90
+ className
91
+ )}
92
+ data-slot="command-list"
93
+ {...props}
94
+ />
95
+ );
96
+ }
97
+
98
+ function CommandEmpty({
99
+ ...props
100
+ }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
101
+ return (
102
+ <CommandPrimitive.Empty
103
+ className="py-6 text-center text-sm"
104
+ data-slot="command-empty"
105
+ {...props}
106
+ />
107
+ );
108
+ }
109
+
110
+ function CommandGroup({
111
+ className,
112
+ ...props
113
+ }: React.ComponentProps<typeof CommandPrimitive.Group>) {
114
+ return (
115
+ <CommandPrimitive.Group
116
+ className={cn(
117
+ 'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:text-xs',
118
+ className
119
+ )}
120
+ data-slot="command-group"
121
+ {...props}
122
+ />
123
+ );
124
+ }
125
+
126
+ function CommandSeparator({
127
+ className,
128
+ ...props
129
+ }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
130
+ return (
131
+ <CommandPrimitive.Separator
132
+ className={cn('-mx-1 h-px bg-border', className)}
133
+ data-slot="command-separator"
134
+ {...props}
135
+ />
136
+ );
137
+ }
138
+
139
+ function CommandItem({
140
+ className,
141
+ ...props
142
+ }: React.ComponentProps<typeof CommandPrimitive.Item>) {
143
+ return (
144
+ <CommandPrimitive.Item
145
+ className={cn(
146
+ "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0",
147
+ className
148
+ )}
149
+ data-slot="command-item"
150
+ {...props}
151
+ />
152
+ );
153
+ }
154
+
155
+ function CommandShortcut({
156
+ className,
157
+ ...props
158
+ }: React.ComponentProps<'span'>) {
159
+ return (
160
+ <span
161
+ className={cn(
162
+ 'ml-auto text-muted-foreground text-xs tracking-widest',
163
+ className
164
+ )}
165
+ data-slot="command-shortcut"
166
+ {...props}
167
+ />
168
+ );
169
+ }
170
+
171
+ export {
172
+ Command,
173
+ CommandDialog,
174
+ CommandInput,
175
+ CommandList,
176
+ CommandEmpty,
177
+ CommandGroup,
178
+ CommandItem,
179
+ CommandShortcut,
180
+ CommandSeparator,
181
+ };