@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.
- package/README.md +194 -53
- package/assets/badges/license.svg +12 -0
- package/assets/badges/npm.svg +13 -0
- package/assets/badges/twitter.svg +22 -0
- package/assets/badges/website.svg +22 -0
- package/package.json +30 -1
- package/src/cli/commands/ask.ts +11 -186
- package/src/cli/commands/models/pull.ts +9 -4
- package/src/cli/commands/serve.ts +19 -0
- package/src/cli/program.ts +28 -0
- package/src/llm/registry.ts +3 -1
- package/src/pipeline/answer.ts +191 -0
- package/src/serve/CLAUDE.md +91 -0
- package/src/serve/bunfig.toml +2 -0
- package/src/serve/context.ts +181 -0
- package/src/serve/index.ts +7 -0
- package/src/serve/public/app.tsx +56 -0
- package/src/serve/public/components/ai-elements/code-block.tsx +176 -0
- package/src/serve/public/components/ai-elements/conversation.tsx +98 -0
- package/src/serve/public/components/ai-elements/inline-citation.tsx +285 -0
- package/src/serve/public/components/ai-elements/loader.tsx +96 -0
- package/src/serve/public/components/ai-elements/message.tsx +443 -0
- package/src/serve/public/components/ai-elements/prompt-input.tsx +1421 -0
- package/src/serve/public/components/ai-elements/sources.tsx +75 -0
- package/src/serve/public/components/ai-elements/suggestion.tsx +51 -0
- package/src/serve/public/components/preset-selector.tsx +403 -0
- package/src/serve/public/components/ui/badge.tsx +46 -0
- package/src/serve/public/components/ui/button-group.tsx +82 -0
- package/src/serve/public/components/ui/button.tsx +62 -0
- package/src/serve/public/components/ui/card.tsx +92 -0
- package/src/serve/public/components/ui/carousel.tsx +244 -0
- package/src/serve/public/components/ui/collapsible.tsx +31 -0
- package/src/serve/public/components/ui/command.tsx +181 -0
- package/src/serve/public/components/ui/dialog.tsx +141 -0
- package/src/serve/public/components/ui/dropdown-menu.tsx +255 -0
- package/src/serve/public/components/ui/hover-card.tsx +42 -0
- package/src/serve/public/components/ui/input-group.tsx +167 -0
- package/src/serve/public/components/ui/input.tsx +21 -0
- package/src/serve/public/components/ui/progress.tsx +28 -0
- package/src/serve/public/components/ui/scroll-area.tsx +56 -0
- package/src/serve/public/components/ui/select.tsx +188 -0
- package/src/serve/public/components/ui/separator.tsx +26 -0
- package/src/serve/public/components/ui/table.tsx +114 -0
- package/src/serve/public/components/ui/textarea.tsx +18 -0
- package/src/serve/public/components/ui/tooltip.tsx +59 -0
- package/src/serve/public/globals.css +226 -0
- package/src/serve/public/hooks/use-api.ts +112 -0
- package/src/serve/public/index.html +13 -0
- package/src/serve/public/pages/Ask.tsx +442 -0
- package/src/serve/public/pages/Browse.tsx +270 -0
- package/src/serve/public/pages/Dashboard.tsx +202 -0
- package/src/serve/public/pages/DocView.tsx +302 -0
- package/src/serve/public/pages/Search.tsx +335 -0
- package/src/serve/routes/api.ts +763 -0
- package/src/serve/server.ts +249 -0
- package/src/store/sqlite/adapter.ts +47 -0
- 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
|
+
};
|