@openconsole/shadcn 0.2.6 → 0.2.7

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 (113) hide show
  1. package/components/index.ts +1 -2
  2. package/components/ui/accordion.tsx +66 -66
  3. package/components/ui/alert-dialog.tsx +196 -196
  4. package/components/ui/alert.tsx +66 -66
  5. package/components/ui/aspect-ratio.tsx +11 -11
  6. package/components/ui/avatar.tsx +53 -53
  7. package/components/ui/badge.tsx +46 -46
  8. package/components/ui/breadcrumb.tsx +109 -109
  9. package/components/ui/button-group.tsx +83 -83
  10. package/components/ui/button.tsx +60 -60
  11. package/components/ui/calendar.tsx +219 -219
  12. package/components/ui/card.tsx +92 -92
  13. package/components/ui/carousel.tsx +241 -241
  14. package/components/ui/chart.tsx +374 -374
  15. package/components/ui/checkbox.tsx +32 -32
  16. package/components/ui/collapsible.tsx +33 -33
  17. package/components/ui/command.tsx +184 -184
  18. package/components/ui/context-menu.tsx +252 -252
  19. package/components/ui/dialog.tsx +143 -143
  20. package/components/ui/direction.tsx +22 -22
  21. package/components/ui/drawer.tsx +135 -135
  22. package/components/ui/dropdown-menu.tsx +257 -257
  23. package/components/ui/empty.tsx +104 -104
  24. package/components/ui/field.tsx +248 -248
  25. package/components/ui/form.tsx +167 -167
  26. package/components/ui/hover-card.tsx +44 -44
  27. package/components/ui/index.ts +59 -59
  28. package/components/ui/input-group.tsx +170 -170
  29. package/components/ui/input-otp.tsx +77 -77
  30. package/components/ui/input.tsx +21 -21
  31. package/components/ui/item.tsx +193 -193
  32. package/components/ui/kbd.tsx +28 -28
  33. package/components/ui/label.tsx +24 -24
  34. package/components/ui/menubar.tsx +276 -276
  35. package/components/ui/native-select.tsx +62 -62
  36. package/components/ui/navigation-menu.tsx +168 -168
  37. package/components/ui/pagination.tsx +127 -127
  38. package/components/ui/popover.tsx +89 -89
  39. package/components/ui/progress.tsx +31 -31
  40. package/components/ui/radio-group.tsx +45 -45
  41. package/components/ui/resizable.tsx +53 -53
  42. package/components/ui/scroll-area.tsx +58 -58
  43. package/components/ui/select.tsx +187 -187
  44. package/components/ui/separator.tsx +28 -28
  45. package/components/ui/sheet.tsx +139 -139
  46. package/components/ui/sidebar.tsx +724 -724
  47. package/components/ui/skeleton.tsx +13 -13
  48. package/components/ui/slider.tsx +63 -63
  49. package/components/ui/sonner.tsx +40 -40
  50. package/components/ui/spinner.tsx +16 -16
  51. package/components/ui/switch.tsx +35 -35
  52. package/components/ui/table.tsx +116 -116
  53. package/components/ui/tabs.tsx +66 -66
  54. package/components/ui/textarea.tsx +18 -18
  55. package/components/ui/toggle-group.tsx +83 -83
  56. package/components/ui/toggle.tsx +47 -47
  57. package/components/ui/tooltip.tsx +61 -61
  58. package/hooks/index.ts +1 -1
  59. package/hooks/use-mobile.ts +19 -19
  60. package/index.ts +3 -3
  61. package/lib/index.ts +1 -1
  62. package/lib/utils.ts +6 -6
  63. package/package.json +1 -1
  64. package/styles.css +124 -124
  65. package/components/ai-elements/agent.tsx +0 -141
  66. package/components/ai-elements/artifact.tsx +0 -148
  67. package/components/ai-elements/attachments.tsx +0 -426
  68. package/components/ai-elements/audio-player.tsx +0 -231
  69. package/components/ai-elements/canvas.tsx +0 -26
  70. package/components/ai-elements/chain-of-thought.tsx +0 -222
  71. package/components/ai-elements/checkpoint.tsx +0 -71
  72. package/components/ai-elements/code-block.tsx +0 -562
  73. package/components/ai-elements/commit.tsx +0 -458
  74. package/components/ai-elements/confirmation.tsx +0 -174
  75. package/components/ai-elements/connection.tsx +0 -28
  76. package/components/ai-elements/context.tsx +0 -409
  77. package/components/ai-elements/controls.tsx +0 -18
  78. package/components/ai-elements/conversation.tsx +0 -168
  79. package/components/ai-elements/edge.tsx +0 -143
  80. package/components/ai-elements/environment-variables.tsx +0 -324
  81. package/components/ai-elements/file-tree.tsx +0 -304
  82. package/components/ai-elements/image.tsx +0 -24
  83. package/components/ai-elements/index.ts +0 -51
  84. package/components/ai-elements/inline-citation.tsx +0 -296
  85. package/components/ai-elements/jsx-preview.tsx +0 -310
  86. package/components/ai-elements/message.tsx +0 -360
  87. package/components/ai-elements/mic-selector.tsx +0 -375
  88. package/components/ai-elements/model-selector.tsx +0 -213
  89. package/components/ai-elements/node.tsx +0 -71
  90. package/components/ai-elements/open-in-chat.tsx +0 -370
  91. package/components/ai-elements/package-info.tsx +0 -239
  92. package/components/ai-elements/panel.tsx +0 -15
  93. package/components/ai-elements/persona.tsx +0 -306
  94. package/components/ai-elements/plan.tsx +0 -147
  95. package/components/ai-elements/prompt-input.tsx +0 -1463
  96. package/components/ai-elements/queue.tsx +0 -274
  97. package/components/ai-elements/reasoning.tsx +0 -228
  98. package/components/ai-elements/sandbox.tsx +0 -132
  99. package/components/ai-elements/schema-display.tsx +0 -471
  100. package/components/ai-elements/shimmer.tsx +0 -77
  101. package/components/ai-elements/snippet.tsx +0 -145
  102. package/components/ai-elements/sources.tsx +0 -77
  103. package/components/ai-elements/speech-input.tsx +0 -323
  104. package/components/ai-elements/stack-trace.tsx +0 -528
  105. package/components/ai-elements/suggestion.tsx +0 -57
  106. package/components/ai-elements/task.tsx +0 -87
  107. package/components/ai-elements/terminal.tsx +0 -273
  108. package/components/ai-elements/test-results.tsx +0 -496
  109. package/components/ai-elements/tool.tsx +0 -173
  110. package/components/ai-elements/toolbar.tsx +0 -16
  111. package/components/ai-elements/transcription.tsx +0 -125
  112. package/components/ai-elements/voice-selector.tsx +0 -524
  113. package/components/ai-elements/web-preview.tsx +0 -281
@@ -1,528 +0,0 @@
1
- "use client";
2
-
3
- import { useControllableState } from "@radix-ui/react-use-controllable-state";
4
- import { Button } from "../ui/button";
5
- import {
6
- Collapsible,
7
- CollapsibleContent,
8
- CollapsibleTrigger,
9
- } from "../ui/collapsible";
10
- import { cn } from "../../lib/utils";
11
- import {
12
- AlertTriangleIcon,
13
- CheckIcon,
14
- ChevronDownIcon,
15
- CopyIcon,
16
- } from "lucide-react";
17
- import type { ComponentProps } from "react";
18
- import {
19
- createContext,
20
- memo,
21
- useCallback,
22
- useContext,
23
- useEffect,
24
- useMemo,
25
- useRef,
26
- useState,
27
- } from "react";
28
-
29
- // Regex patterns for parsing stack traces
30
- const STACK_FRAME_WITH_PARENS_REGEX = /^at\s+(.+?)\s+\((.+):(\d+):(\d+)\)$/;
31
- const STACK_FRAME_WITHOUT_FN_REGEX = /^at\s+(.+):(\d+):(\d+)$/;
32
- const ERROR_TYPE_REGEX = /^(\w+Error|Error):\s*(.*)$/;
33
- const AT_PREFIX_REGEX = /^at\s+/;
34
-
35
- interface StackFrame {
36
- raw: string;
37
- functionName: string | null;
38
- filePath: string | null;
39
- lineNumber: number | null;
40
- columnNumber: number | null;
41
- isInternal: boolean;
42
- }
43
-
44
- interface ParsedStackTrace {
45
- errorType: string | null;
46
- errorMessage: string;
47
- frames: StackFrame[];
48
- raw: string;
49
- }
50
-
51
- interface StackTraceContextValue {
52
- trace: ParsedStackTrace;
53
- raw: string;
54
- isOpen: boolean;
55
- setIsOpen: (open: boolean) => void;
56
- onFilePathClick?: (filePath: string, line?: number, column?: number) => void;
57
- }
58
-
59
- const StackTraceContext = createContext<StackTraceContextValue | null>(null);
60
-
61
- const useStackTrace = () => {
62
- const context = useContext(StackTraceContext);
63
- if (!context) {
64
- throw new Error("StackTrace components must be used within StackTrace");
65
- }
66
- return context;
67
- };
68
-
69
- const parseStackFrame = (line: string): StackFrame => {
70
- const trimmed = line.trim();
71
-
72
- // Pattern: at functionName (filePath:line:column)
73
- const withParensMatch = trimmed.match(STACK_FRAME_WITH_PARENS_REGEX);
74
- if (withParensMatch) {
75
- const [, functionName, filePath, lineNum, colNum] = withParensMatch;
76
- const isInternal =
77
- filePath.includes("node_modules") ||
78
- filePath.startsWith("node:") ||
79
- filePath.includes("internal/");
80
- return {
81
- columnNumber: colNum ? Number.parseInt(colNum, 10) : null,
82
- filePath: filePath ?? null,
83
- functionName: functionName ?? null,
84
- isInternal,
85
- lineNumber: lineNum ? Number.parseInt(lineNum, 10) : null,
86
- raw: trimmed,
87
- };
88
- }
89
-
90
- // Pattern: at filePath:line:column (no function name)
91
- const withoutFnMatch = trimmed.match(STACK_FRAME_WITHOUT_FN_REGEX);
92
- if (withoutFnMatch) {
93
- const [, filePath, lineNum, colNum] = withoutFnMatch;
94
- const isInternal =
95
- (filePath?.includes("node_modules") ?? false) ||
96
- (filePath?.startsWith("node:") ?? false) ||
97
- (filePath?.includes("internal/") ?? false);
98
- return {
99
- columnNumber: colNum ? Number.parseInt(colNum, 10) : null,
100
- filePath: filePath ?? null,
101
- functionName: null,
102
- isInternal,
103
- lineNumber: lineNum ? Number.parseInt(lineNum, 10) : null,
104
- raw: trimmed,
105
- };
106
- }
107
-
108
- // Fallback: unparseable line
109
- return {
110
- columnNumber: null,
111
- filePath: null,
112
- functionName: null,
113
- isInternal: trimmed.includes("node_modules") || trimmed.includes("node:"),
114
- lineNumber: null,
115
- raw: trimmed,
116
- };
117
- };
118
-
119
- const parseStackTrace = (trace: string): ParsedStackTrace => {
120
- const lines = trace.split("\n").filter((line) => line.trim());
121
-
122
- if (lines.length === 0) {
123
- return {
124
- errorMessage: trace,
125
- errorType: null,
126
- frames: [],
127
- raw: trace,
128
- };
129
- }
130
-
131
- const firstLine = lines[0].trim();
132
- let errorType: string | null = null;
133
- let errorMessage = firstLine;
134
-
135
- // Try to extract error type from "ErrorType: message" format
136
- const errorMatch = firstLine.match(ERROR_TYPE_REGEX);
137
- if (errorMatch) {
138
- const [, type, msg] = errorMatch;
139
- errorType = type;
140
- errorMessage = msg || "";
141
- }
142
-
143
- // Parse stack frames (lines starting with "at")
144
- const frames = lines
145
- .slice(1)
146
- .filter((line) => line.trim().startsWith("at "))
147
- .map(parseStackFrame);
148
-
149
- return {
150
- errorMessage,
151
- errorType,
152
- frames,
153
- raw: trace,
154
- };
155
- };
156
-
157
- export type StackTraceProps = ComponentProps<"div"> & {
158
- trace: string;
159
- open?: boolean;
160
- defaultOpen?: boolean;
161
- onOpenChange?: (open: boolean) => void;
162
- onFilePathClick?: (filePath: string, line?: number, column?: number) => void;
163
- };
164
-
165
- export const StackTrace = memo(
166
- ({
167
- trace,
168
- className,
169
- open,
170
- defaultOpen = false,
171
- onOpenChange,
172
- onFilePathClick,
173
- children,
174
- ...props
175
- }: StackTraceProps) => {
176
- const [isOpen, setIsOpen] = useControllableState({
177
- defaultProp: defaultOpen,
178
- onChange: onOpenChange,
179
- prop: open,
180
- });
181
-
182
- const parsedTrace = useMemo(() => parseStackTrace(trace), [trace]);
183
-
184
- const contextValue = useMemo(
185
- () => ({
186
- isOpen,
187
- onFilePathClick,
188
- raw: trace,
189
- setIsOpen,
190
- trace: parsedTrace,
191
- }),
192
- [parsedTrace, trace, isOpen, setIsOpen, onFilePathClick]
193
- );
194
-
195
- return (
196
- <StackTraceContext.Provider value={contextValue}>
197
- <div
198
- className={cn(
199
- "not-prose w-full overflow-hidden rounded-lg border bg-background font-mono text-sm",
200
- className
201
- )}
202
- {...props}
203
- >
204
- {children}
205
- </div>
206
- </StackTraceContext.Provider>
207
- );
208
- }
209
- );
210
-
211
- export type StackTraceHeaderProps = ComponentProps<typeof CollapsibleTrigger>;
212
-
213
- export const StackTraceHeader = memo(
214
- ({ className, children, ...props }: StackTraceHeaderProps) => {
215
- const { isOpen, setIsOpen } = useStackTrace();
216
-
217
- return (
218
- <Collapsible onOpenChange={setIsOpen} open={isOpen}>
219
- <CollapsibleTrigger asChild {...props}>
220
- <div
221
- className={cn(
222
- "flex w-full cursor-pointer items-center gap-3 p-3 text-left transition-colors hover:bg-muted/50",
223
- className
224
- )}
225
- >
226
- {children}
227
- </div>
228
- </CollapsibleTrigger>
229
- </Collapsible>
230
- );
231
- }
232
- );
233
-
234
- export type StackTraceErrorProps = ComponentProps<"div">;
235
-
236
- export const StackTraceError = memo(
237
- ({ className, children, ...props }: StackTraceErrorProps) => (
238
- <div
239
- className={cn(
240
- "flex flex-1 items-center gap-2 overflow-hidden",
241
- className
242
- )}
243
- {...props}
244
- >
245
- <AlertTriangleIcon className="size-4 shrink-0 text-destructive" />
246
- {children}
247
- </div>
248
- )
249
- );
250
-
251
- export type StackTraceErrorTypeProps = ComponentProps<"span">;
252
-
253
- export const StackTraceErrorType = memo(
254
- ({ className, children, ...props }: StackTraceErrorTypeProps) => {
255
- const { trace } = useStackTrace();
256
-
257
- return (
258
- <span
259
- className={cn("shrink-0 font-semibold text-destructive", className)}
260
- {...props}
261
- >
262
- {children ?? trace.errorType}
263
- </span>
264
- );
265
- }
266
- );
267
-
268
- export type StackTraceErrorMessageProps = ComponentProps<"span">;
269
-
270
- export const StackTraceErrorMessage = memo(
271
- ({ className, children, ...props }: StackTraceErrorMessageProps) => {
272
- const { trace } = useStackTrace();
273
-
274
- return (
275
- <span className={cn("truncate text-foreground", className)} {...props}>
276
- {children ?? trace.errorMessage}
277
- </span>
278
- );
279
- }
280
- );
281
-
282
- export type StackTraceActionsProps = ComponentProps<"div">;
283
-
284
- const handleActionsClick = (e: React.MouseEvent) => e.stopPropagation();
285
- const handleActionsKeyDown = (e: React.KeyboardEvent) => {
286
- if (e.key === "Enter" || e.key === " ") {
287
- e.stopPropagation();
288
- }
289
- };
290
-
291
- export const StackTraceActions = memo(
292
- ({ className, children, ...props }: StackTraceActionsProps) => (
293
- <div
294
- className={cn("flex shrink-0 items-center gap-1", className)}
295
- onClick={handleActionsClick}
296
- onKeyDown={handleActionsKeyDown}
297
- role="group"
298
- {...props}
299
- >
300
- {children}
301
- </div>
302
- )
303
- );
304
-
305
- export type StackTraceCopyButtonProps = ComponentProps<typeof Button> & {
306
- onCopy?: () => void;
307
- onError?: (error: Error) => void;
308
- timeout?: number;
309
- };
310
-
311
- export const StackTraceCopyButton = memo(
312
- ({
313
- onCopy,
314
- onError,
315
- timeout = 2000,
316
- className,
317
- children,
318
- ...props
319
- }: StackTraceCopyButtonProps) => {
320
- const [isCopied, setIsCopied] = useState(false);
321
- const timeoutRef = useRef<number>(0);
322
- const { raw } = useStackTrace();
323
-
324
- const copyToClipboard = useCallback(async () => {
325
- if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
326
- onError?.(new Error("Clipboard API not available"));
327
- return;
328
- }
329
-
330
- try {
331
- await navigator.clipboard.writeText(raw);
332
- setIsCopied(true);
333
- onCopy?.();
334
- timeoutRef.current = window.setTimeout(
335
- () => setIsCopied(false),
336
- timeout
337
- );
338
- } catch (error) {
339
- onError?.(error as Error);
340
- }
341
- }, [raw, onCopy, onError, timeout]);
342
-
343
- useEffect(
344
- () => () => {
345
- window.clearTimeout(timeoutRef.current);
346
- },
347
- []
348
- );
349
-
350
- const Icon = isCopied ? CheckIcon : CopyIcon;
351
-
352
- return (
353
- <Button
354
- className={cn("size-7", className)}
355
- onClick={copyToClipboard}
356
- size="icon"
357
- variant="ghost"
358
- {...props}
359
- >
360
- {children ?? <Icon size={14} />}
361
- </Button>
362
- );
363
- }
364
- );
365
-
366
- export type StackTraceExpandButtonProps = ComponentProps<"div">;
367
-
368
- export const StackTraceExpandButton = memo(
369
- ({ className, ...props }: StackTraceExpandButtonProps) => {
370
- const { isOpen } = useStackTrace();
371
-
372
- return (
373
- <div
374
- className={cn("flex size-7 items-center justify-center", className)}
375
- {...props}
376
- >
377
- <ChevronDownIcon
378
- className={cn(
379
- "size-4 text-muted-foreground transition-transform",
380
- isOpen ? "rotate-180" : "rotate-0"
381
- )}
382
- />
383
- </div>
384
- );
385
- }
386
- );
387
-
388
- export type StackTraceContentProps = ComponentProps<
389
- typeof CollapsibleContent
390
- > & {
391
- maxHeight?: number;
392
- };
393
-
394
- export const StackTraceContent = memo(
395
- ({
396
- className,
397
- maxHeight = 400,
398
- children,
399
- ...props
400
- }: StackTraceContentProps) => {
401
- const { isOpen } = useStackTrace();
402
-
403
- return (
404
- <Collapsible open={isOpen}>
405
- <CollapsibleContent
406
- className={cn(
407
- "overflow-auto border-t bg-muted/30",
408
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:animate-out data-[state=open]:animate-in",
409
- className
410
- )}
411
- style={{ maxHeight }}
412
- {...props}
413
- >
414
- {children}
415
- </CollapsibleContent>
416
- </Collapsible>
417
- );
418
- }
419
- );
420
-
421
- export type StackTraceFramesProps = ComponentProps<"div"> & {
422
- showInternalFrames?: boolean;
423
- };
424
-
425
- interface FilePathButtonProps {
426
- frame: StackFrame;
427
- onFilePathClick?: (
428
- filePath: string,
429
- lineNumber?: number,
430
- columnNumber?: number
431
- ) => void;
432
- }
433
-
434
- const FilePathButton = memo(
435
- ({ frame, onFilePathClick }: FilePathButtonProps) => {
436
- const handleClick = useCallback(() => {
437
- if (frame.filePath) {
438
- onFilePathClick?.(
439
- frame.filePath,
440
- frame.lineNumber ?? undefined,
441
- frame.columnNumber ?? undefined
442
- );
443
- }
444
- }, [frame, onFilePathClick]);
445
-
446
- return (
447
- <button
448
- className={cn(
449
- "underline decoration-dotted hover:text-primary",
450
- onFilePathClick && "cursor-pointer"
451
- )}
452
- disabled={!onFilePathClick}
453
- onClick={handleClick}
454
- type="button"
455
- >
456
- {frame.filePath}
457
- {frame.lineNumber !== null && `:${frame.lineNumber}`}
458
- {frame.columnNumber !== null && `:${frame.columnNumber}`}
459
- </button>
460
- );
461
- }
462
- );
463
-
464
- FilePathButton.displayName = "FilePathButton";
465
-
466
- export const StackTraceFrames = memo(
467
- ({
468
- className,
469
- showInternalFrames = true,
470
- ...props
471
- }: StackTraceFramesProps) => {
472
- const { trace, onFilePathClick } = useStackTrace();
473
-
474
- const framesToShow = showInternalFrames
475
- ? trace.frames
476
- : trace.frames.filter((f) => !f.isInternal);
477
-
478
- return (
479
- <div className={cn("space-y-1 p-3", className)} {...props}>
480
- {framesToShow.map((frame) => (
481
- <div
482
- className={cn(
483
- "text-xs",
484
- frame.isInternal
485
- ? "text-muted-foreground/50"
486
- : "text-foreground/90"
487
- )}
488
- key={frame.raw}
489
- >
490
- <span className="text-muted-foreground">at </span>
491
- {frame.functionName && (
492
- <span className={frame.isInternal ? "" : "text-foreground"}>
493
- {frame.functionName}{" "}
494
- </span>
495
- )}
496
- {frame.filePath && (
497
- <>
498
- <span className="text-muted-foreground">(</span>
499
- <FilePathButton
500
- frame={frame}
501
- onFilePathClick={onFilePathClick}
502
- />
503
- <span className="text-muted-foreground">)</span>
504
- </>
505
- )}
506
- {!(frame.filePath || frame.functionName) && (
507
- <span>{frame.raw.replace(AT_PREFIX_REGEX, "")}</span>
508
- )}
509
- </div>
510
- ))}
511
- {framesToShow.length === 0 && (
512
- <div className="text-muted-foreground text-xs">No stack frames</div>
513
- )}
514
- </div>
515
- );
516
- }
517
- );
518
-
519
- StackTrace.displayName = "StackTrace";
520
- StackTraceHeader.displayName = "StackTraceHeader";
521
- StackTraceError.displayName = "StackTraceError";
522
- StackTraceErrorType.displayName = "StackTraceErrorType";
523
- StackTraceErrorMessage.displayName = "StackTraceErrorMessage";
524
- StackTraceActions.displayName = "StackTraceActions";
525
- StackTraceCopyButton.displayName = "StackTraceCopyButton";
526
- StackTraceExpandButton.displayName = "StackTraceExpandButton";
527
- StackTraceContent.displayName = "StackTraceContent";
528
- StackTraceFrames.displayName = "StackTraceFrames";
@@ -1,57 +0,0 @@
1
- "use client";
2
-
3
- import { Button } from "../ui/button";
4
- import {
5
- ScrollArea,
6
- ScrollBar,
7
- } from "../ui/scroll-area";
8
- import { cn } from "../../lib/utils";
9
- import type { ComponentProps } from "react";
10
- import { useCallback } from "react";
11
-
12
- export type SuggestionsProps = ComponentProps<typeof ScrollArea>;
13
-
14
- export const Suggestions = ({
15
- className,
16
- children,
17
- ...props
18
- }: SuggestionsProps) => (
19
- <ScrollArea className="w-full overflow-x-auto whitespace-nowrap" {...props}>
20
- <div className={cn("flex w-max flex-nowrap items-center gap-2", className)}>
21
- {children}
22
- </div>
23
- <ScrollBar className="hidden" orientation="horizontal" />
24
- </ScrollArea>
25
- );
26
-
27
- export type SuggestionProps = Omit<ComponentProps<typeof Button>, "onClick"> & {
28
- suggestion: string;
29
- onClick?: (suggestion: string) => void;
30
- };
31
-
32
- export const Suggestion = ({
33
- suggestion,
34
- onClick,
35
- className,
36
- variant = "outline",
37
- size = "sm",
38
- children,
39
- ...props
40
- }: SuggestionProps) => {
41
- const handleClick = useCallback(() => {
42
- onClick?.(suggestion);
43
- }, [onClick, suggestion]);
44
-
45
- return (
46
- <Button
47
- className={cn("cursor-pointer rounded-full px-4", className)}
48
- onClick={handleClick}
49
- size={size}
50
- type="button"
51
- variant={variant}
52
- {...props}
53
- >
54
- {children || suggestion}
55
- </Button>
56
- );
57
- };
@@ -1,87 +0,0 @@
1
- "use client";
2
-
3
- import {
4
- Collapsible,
5
- CollapsibleContent,
6
- CollapsibleTrigger,
7
- } from "../ui/collapsible";
8
- import { cn } from "../../lib/utils";
9
- import { ChevronDownIcon, SearchIcon } from "lucide-react";
10
- import type { ComponentProps } from "react";
11
-
12
- export type TaskItemFileProps = ComponentProps<"div">;
13
-
14
- export const TaskItemFile = ({
15
- children,
16
- className,
17
- ...props
18
- }: TaskItemFileProps) => (
19
- <div
20
- className={cn(
21
- "inline-flex items-center gap-1 rounded-md border bg-secondary px-1.5 py-0.5 text-foreground text-xs",
22
- className
23
- )}
24
- {...props}
25
- >
26
- {children}
27
- </div>
28
- );
29
-
30
- export type TaskItemProps = ComponentProps<"div">;
31
-
32
- export const TaskItem = ({ children, className, ...props }: TaskItemProps) => (
33
- <div className={cn("text-muted-foreground text-sm", className)} {...props}>
34
- {children}
35
- </div>
36
- );
37
-
38
- export type TaskProps = ComponentProps<typeof Collapsible>;
39
-
40
- export const Task = ({
41
- defaultOpen = true,
42
- className,
43
- ...props
44
- }: TaskProps) => (
45
- <Collapsible className={cn(className)} defaultOpen={defaultOpen} {...props} />
46
- );
47
-
48
- export type TaskTriggerProps = ComponentProps<typeof CollapsibleTrigger> & {
49
- title: string;
50
- };
51
-
52
- export const TaskTrigger = ({
53
- children,
54
- className,
55
- title,
56
- ...props
57
- }: TaskTriggerProps) => (
58
- <CollapsibleTrigger asChild className={cn("group", className)} {...props}>
59
- {children ?? (
60
- <div className="flex w-full cursor-pointer items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground">
61
- <SearchIcon className="size-4" />
62
- <p className="text-sm">{title}</p>
63
- <ChevronDownIcon className="size-4 transition-transform group-data-[state=open]:rotate-180" />
64
- </div>
65
- )}
66
- </CollapsibleTrigger>
67
- );
68
-
69
- export type TaskContentProps = ComponentProps<typeof CollapsibleContent>;
70
-
71
- export const TaskContent = ({
72
- children,
73
- className,
74
- ...props
75
- }: TaskContentProps) => (
76
- <CollapsibleContent
77
- className={cn(
78
- "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
79
- className
80
- )}
81
- {...props}
82
- >
83
- <div className="mt-4 space-y-2 border-muted border-l-2 pl-4">
84
- {children}
85
- </div>
86
- </CollapsibleContent>
87
- );