@aomi-labs/widget-lib 1.0.0 → 1.1.1

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 (76) hide show
  1. package/dist/accordion.json +18 -0
  2. package/dist/alert.json +17 -0
  3. package/dist/aomi-frame.json +24 -0
  4. package/dist/assistant-thread-list.json +22 -0
  5. package/dist/assistant-thread.json +27 -0
  6. package/dist/assistant-threadlist-sidebar.json +20 -0
  7. package/dist/assistant-tool-fallback.json +20 -0
  8. package/dist/avatar.json +17 -0
  9. package/dist/badge.json +17 -0
  10. package/dist/breadcrumb.json +17 -0
  11. package/dist/button.json +18 -0
  12. package/dist/card.json +15 -0
  13. package/dist/collapsible.json +17 -0
  14. package/dist/command.json +21 -0
  15. package/dist/dialog.json +18 -0
  16. package/dist/drawer.json +17 -0
  17. package/dist/input.json +15 -0
  18. package/dist/label.json +15 -0
  19. package/dist/notification.json +20 -0
  20. package/dist/popover.json +17 -0
  21. package/dist/registry.json +429 -0
  22. package/dist/separator.json +17 -0
  23. package/dist/sheet.json +18 -0
  24. package/dist/sidebar.json +18 -0
  25. package/dist/skeleton.json +15 -0
  26. package/dist/sonner.json +17 -0
  27. package/dist/tooltip.json +17 -0
  28. package/package.json +27 -85
  29. package/src/components/aomi-frame.tsx +221 -0
  30. package/src/components/assistant-ui/attachment.tsx +235 -0
  31. package/src/components/assistant-ui/markdown-text.tsx +228 -0
  32. package/src/components/assistant-ui/thread-list.tsx +106 -0
  33. package/src/components/assistant-ui/thread.tsx +476 -0
  34. package/src/components/assistant-ui/threadlist-sidebar.tsx +66 -0
  35. package/src/components/assistant-ui/tool-fallback.tsx +48 -0
  36. package/src/components/assistant-ui/tooltip-icon-button.tsx +42 -0
  37. package/src/components/control-bar/api-key-input.tsx +122 -0
  38. package/src/components/control-bar/index.tsx +58 -0
  39. package/src/components/control-bar/model-select.tsx +120 -0
  40. package/src/components/control-bar/namespace-select.tsx +117 -0
  41. package/src/components/control-bar/wallet-connect.tsx +75 -0
  42. package/src/components/test/ThreadContextTest.tsx +204 -0
  43. package/src/components/tools/example-tool/ExampleTool.tsx +102 -0
  44. package/src/components/ui/accordion.tsx +58 -0
  45. package/src/components/ui/alert.tsx +62 -0
  46. package/src/components/ui/avatar.tsx +53 -0
  47. package/src/components/ui/badge.tsx +37 -0
  48. package/src/components/ui/breadcrumb.tsx +109 -0
  49. package/src/components/ui/button.tsx +59 -0
  50. package/src/components/ui/card.tsx +86 -0
  51. package/src/components/ui/collapsible.tsx +12 -0
  52. package/src/components/ui/command.tsx +156 -0
  53. package/src/components/ui/dialog.tsx +143 -0
  54. package/src/components/ui/drawer.tsx +118 -0
  55. package/src/components/ui/input.tsx +21 -0
  56. package/src/components/ui/label.tsx +20 -0
  57. package/src/components/ui/notification.tsx +57 -0
  58. package/src/components/ui/popover.tsx +33 -0
  59. package/src/components/ui/separator.tsx +28 -0
  60. package/src/components/ui/sheet.tsx +139 -0
  61. package/src/components/ui/sidebar.tsx +827 -0
  62. package/src/components/ui/skeleton.tsx +15 -0
  63. package/src/components/ui/sonner.tsx +29 -0
  64. package/src/components/ui/tooltip.tsx +61 -0
  65. package/src/hooks/use-mobile.ts +21 -0
  66. package/src/index.ts +26 -0
  67. package/src/registry.ts +218 -0
  68. package/{dist/styles.css → src/themes/default.css} +21 -3
  69. package/src/themes/tokens.config.ts +39 -0
  70. package/README.md +0 -41
  71. package/dist/index.cjs +0 -3780
  72. package/dist/index.cjs.map +0 -1
  73. package/dist/index.d.cts +0 -302
  74. package/dist/index.d.ts +0 -302
  75. package/dist/index.js +0 -3696
  76. package/dist/index.js.map +0 -1
@@ -0,0 +1,102 @@
1
+ "use client";
2
+
3
+ import { makeAssistantToolUI } from "@assistant-ui/react";
4
+ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
5
+
6
+ /**
7
+ * Example ToolUI Component
8
+ *
9
+ * This demonstrates how to create a custom UI for tool calls.
10
+ * Replace this with your actual tool implementation.
11
+ *
12
+ * Usage:
13
+ * 1. Define your tool args and result types
14
+ * 2. Update toolName to match your backend tool
15
+ * 3. Customize the render function with your UI
16
+ * 4. Import and render <ExampleTool /> in your page
17
+ */
18
+
19
+ // Define the shape of your tool's arguments
20
+ type ExampleToolArgs = {
21
+ query: string;
22
+ limit?: number;
23
+ };
24
+
25
+ // Define the shape of your tool's result
26
+ type ExampleToolResult = {
27
+ data: Array<{
28
+ id: string;
29
+ title: string;
30
+ description: string;
31
+ }>;
32
+ total: number;
33
+ };
34
+
35
+ export const ExampleTool = makeAssistantToolUI<
36
+ ExampleToolArgs,
37
+ ExampleToolResult
38
+ >({
39
+ // IMPORTANT: Must match the tool name from your backend exactly!
40
+ toolName: "example_tool",
41
+
42
+ render: function ExampleToolUI({ args, argsText, result, status }) {
43
+ return (
44
+ <div className="my-4">
45
+ {/* Show the tool call */}
46
+ <pre className="text-muted-foreground mb-2 text-xs">
47
+ example_tool({argsText})
48
+ </pre>
49
+
50
+ <Card>
51
+ <CardHeader>
52
+ <CardTitle className="text-lg">
53
+ {status.type === "running" ? "Searching..." : "Search Results"}
54
+ </CardTitle>
55
+ </CardHeader>
56
+ <CardContent>
57
+ {/* Loading state */}
58
+ {status.type === "running" && (
59
+ <div className="flex items-center gap-2">
60
+ <div className="border-primary h-4 w-4 animate-spin rounded-full border-2 border-t-transparent" />
61
+ <span className="text-sm">
62
+ Searching for &quot;{args.query}&quot;...
63
+ </span>
64
+ </div>
65
+ )}
66
+
67
+ {/* Results */}
68
+ {result && (
69
+ <div className="space-y-3">
70
+ <p className="text-muted-foreground text-sm">
71
+ Found {result.total} results
72
+ {args.limit && ` (showing top ${args.limit})`}
73
+ </p>
74
+
75
+ <div className="space-y-2">
76
+ {result.data.map((item) => (
77
+ <div
78
+ key={item.id}
79
+ className="hover:bg-muted/50 rounded-lg border p-3 transition-colors"
80
+ >
81
+ <h4 className="font-medium">{item.title}</h4>
82
+ <p className="text-muted-foreground mt-1 text-sm">
83
+ {item.description}
84
+ </p>
85
+ </div>
86
+ ))}
87
+ </div>
88
+ </div>
89
+ )}
90
+
91
+ {/* Error state (if your result includes error) */}
92
+ {status.type === "incomplete" && (
93
+ <div className="text-destructive text-sm">
94
+ Failed to complete the search
95
+ </div>
96
+ )}
97
+ </CardContent>
98
+ </Card>
99
+ </div>
100
+ );
101
+ },
102
+ });
@@ -0,0 +1,58 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as AccordionPrimitive from "@radix-ui/react-accordion";
5
+ import { ChevronDown } from "lucide-react";
6
+
7
+ import { cn } from "@aomi-labs/react";
8
+
9
+ const Accordion = AccordionPrimitive.Root;
10
+
11
+ const AccordionItem = React.forwardRef<
12
+ React.ElementRef<typeof AccordionPrimitive.Item>,
13
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
14
+ >(({ className, ...props }, ref) => (
15
+ <AccordionPrimitive.Item
16
+ ref={ref}
17
+ className={cn("border-b", className)}
18
+ {...props}
19
+ />
20
+ ));
21
+ AccordionItem.displayName = "AccordionItem";
22
+
23
+ const AccordionTrigger = React.forwardRef<
24
+ React.ElementRef<typeof AccordionPrimitive.Trigger>,
25
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
26
+ >(({ className, children, ...props }, ref) => (
27
+ <AccordionPrimitive.Header className="flex">
28
+ <AccordionPrimitive.Trigger
29
+ ref={ref}
30
+ className={cn(
31
+ "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
32
+ className,
33
+ )}
34
+ {...props}
35
+ >
36
+ {children}
37
+ <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
38
+ </AccordionPrimitive.Trigger>
39
+ </AccordionPrimitive.Header>
40
+ ));
41
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
42
+
43
+ const AccordionContent = React.forwardRef<
44
+ React.ElementRef<typeof AccordionPrimitive.Content>,
45
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
46
+ >(({ className, children, ...props }, ref) => (
47
+ <AccordionPrimitive.Content
48
+ ref={ref}
49
+ className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all"
50
+ {...props}
51
+ >
52
+ <div className={cn("pb-4 pt-0", className)}>{children}</div>
53
+ </AccordionPrimitive.Content>
54
+ ));
55
+
56
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName;
57
+
58
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
@@ -0,0 +1,62 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "@aomi-labs/react";
5
+
6
+ const alertVariants = cva(
7
+ "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: "bg-background text-foreground",
12
+ destructive:
13
+ "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
14
+ },
15
+ },
16
+ defaultVariants: {
17
+ variant: "default",
18
+ },
19
+ },
20
+ );
21
+
22
+ const Alert = React.forwardRef<
23
+ HTMLDivElement,
24
+ React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
25
+ >(({ className, variant, ...props }, ref) => (
26
+ <div
27
+ ref={ref}
28
+ role="alert"
29
+ data-slot="alert"
30
+ className={cn(alertVariants({ variant }), className)}
31
+ {...props}
32
+ />
33
+ ));
34
+ Alert.displayName = "Alert";
35
+
36
+ const AlertTitle = React.forwardRef<
37
+ HTMLParagraphElement,
38
+ React.HTMLAttributes<HTMLHeadingElement>
39
+ >(({ className, ...props }, ref) => (
40
+ <h5
41
+ ref={ref}
42
+ data-slot="alert-title"
43
+ className={cn("mb-1 font-medium leading-none tracking-tight", className)}
44
+ {...props}
45
+ />
46
+ ));
47
+ AlertTitle.displayName = "AlertTitle";
48
+
49
+ const AlertDescription = React.forwardRef<
50
+ HTMLParagraphElement,
51
+ React.HTMLAttributes<HTMLParagraphElement>
52
+ >(({ className, ...props }, ref) => (
53
+ <div
54
+ ref={ref}
55
+ data-slot="alert-description"
56
+ className={cn("text-sm [&_p]:leading-relaxed", className)}
57
+ {...props}
58
+ />
59
+ ));
60
+ AlertDescription.displayName = "AlertDescription";
61
+
62
+ export { Alert, AlertTitle, AlertDescription };
@@ -0,0 +1,53 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
5
+
6
+ import { cn } from "@aomi-labs/react";
7
+
8
+ function Avatar({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
12
+ return (
13
+ <AvatarPrimitive.Root
14
+ data-slot="avatar"
15
+ className={cn(
16
+ "relative flex size-8 shrink-0 overflow-hidden rounded-full",
17
+ className,
18
+ )}
19
+ {...props}
20
+ />
21
+ );
22
+ }
23
+
24
+ function AvatarImage({
25
+ className,
26
+ ...props
27
+ }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
28
+ return (
29
+ <AvatarPrimitive.Image
30
+ data-slot="avatar-image"
31
+ className={cn("aspect-square size-full", className)}
32
+ {...props}
33
+ />
34
+ );
35
+ }
36
+
37
+ function AvatarFallback({
38
+ className,
39
+ ...props
40
+ }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
41
+ return (
42
+ <AvatarPrimitive.Fallback
43
+ data-slot="avatar-fallback"
44
+ className={cn(
45
+ "bg-muted flex size-full items-center justify-center rounded-full",
46
+ className,
47
+ )}
48
+ {...props}
49
+ />
50
+ );
51
+ }
52
+
53
+ export { Avatar, AvatarImage, AvatarFallback };
@@ -0,0 +1,37 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "@aomi-labs/react";
5
+
6
+ const badgeVariants = cva(
7
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default:
12
+ "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
13
+ secondary:
14
+ "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15
+ destructive:
16
+ "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
17
+ outline: "text-foreground",
18
+ },
19
+ },
20
+ defaultVariants: {
21
+ variant: "default",
22
+ },
23
+ },
24
+ );
25
+
26
+ export interface BadgeProps
27
+ extends
28
+ React.HTMLAttributes<HTMLDivElement>,
29
+ VariantProps<typeof badgeVariants> {}
30
+
31
+ function Badge({ className, variant, ...props }: BadgeProps) {
32
+ return (
33
+ <div className={cn(badgeVariants({ variant }), className)} {...props} />
34
+ );
35
+ }
36
+
37
+ export { Badge, badgeVariants };
@@ -0,0 +1,109 @@
1
+ import * as React from "react";
2
+ import { Slot } from "@radix-ui/react-slot";
3
+ import { ChevronRight, MoreHorizontal } from "lucide-react";
4
+
5
+ import { cn } from "@aomi-labs/react";
6
+
7
+ function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
8
+ return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />;
9
+ }
10
+
11
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
12
+ return (
13
+ <ol
14
+ data-slot="breadcrumb-list"
15
+ className={cn(
16
+ "text-muted-foreground flex flex-wrap items-center gap-1.5 break-words text-sm sm:gap-2.5",
17
+ className,
18
+ )}
19
+ {...props}
20
+ />
21
+ );
22
+ }
23
+
24
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
25
+ return (
26
+ <li
27
+ data-slot="breadcrumb-item"
28
+ className={cn("inline-flex items-center gap-1.5", className)}
29
+ {...props}
30
+ />
31
+ );
32
+ }
33
+
34
+ function BreadcrumbLink({
35
+ asChild,
36
+ className,
37
+ ...props
38
+ }: React.ComponentProps<"a"> & {
39
+ asChild?: boolean;
40
+ }) {
41
+ const Comp = asChild ? Slot : "a";
42
+
43
+ return (
44
+ <Comp
45
+ data-slot="breadcrumb-link"
46
+ className={cn("hover:text-foreground transition-colors", className)}
47
+ {...props}
48
+ />
49
+ );
50
+ }
51
+
52
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
53
+ return (
54
+ <span
55
+ data-slot="breadcrumb-page"
56
+ role="link"
57
+ aria-disabled="true"
58
+ aria-current="page"
59
+ className={cn("text-foreground font-normal", className)}
60
+ {...props}
61
+ />
62
+ );
63
+ }
64
+
65
+ function BreadcrumbSeparator({
66
+ children,
67
+ className,
68
+ ...props
69
+ }: React.ComponentProps<"li">) {
70
+ return (
71
+ <li
72
+ data-slot="breadcrumb-separator"
73
+ role="presentation"
74
+ aria-hidden="true"
75
+ className={cn("[&>svg]:size-3.5", className)}
76
+ {...props}
77
+ >
78
+ {children ?? <ChevronRight />}
79
+ </li>
80
+ );
81
+ }
82
+
83
+ function BreadcrumbEllipsis({
84
+ className,
85
+ ...props
86
+ }: React.ComponentProps<"span">) {
87
+ return (
88
+ <span
89
+ data-slot="breadcrumb-ellipsis"
90
+ role="presentation"
91
+ aria-hidden="true"
92
+ className={cn("flex size-9 items-center justify-center", className)}
93
+ {...props}
94
+ >
95
+ <MoreHorizontal className="size-4" />
96
+ <span className="sr-only">More</span>
97
+ </span>
98
+ );
99
+ }
100
+
101
+ export {
102
+ Breadcrumb,
103
+ BreadcrumbList,
104
+ BreadcrumbItem,
105
+ BreadcrumbLink,
106
+ BreadcrumbPage,
107
+ BreadcrumbSeparator,
108
+ BreadcrumbEllipsis,
109
+ };
@@ -0,0 +1,59 @@
1
+ import * as React from "react";
2
+ import { Slot } from "@radix-ui/react-slot";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+
5
+ import { cn } from "@aomi-labs/react";
6
+
7
+ const buttonVariants = cva(
8
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default:
13
+ "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
14
+ destructive:
15
+ "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
16
+ outline:
17
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
18
+ secondary:
19
+ "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
20
+ ghost:
21
+ "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
22
+ link: "text-primary underline-offset-4 hover:underline",
23
+ },
24
+ size: {
25
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
26
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
27
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
28
+ icon: "size-9",
29
+ },
30
+ },
31
+ defaultVariants: {
32
+ variant: "default",
33
+ size: "default",
34
+ },
35
+ },
36
+ );
37
+
38
+ function Button({
39
+ className,
40
+ variant,
41
+ size,
42
+ asChild = false,
43
+ ...props
44
+ }: React.ComponentProps<"button"> &
45
+ VariantProps<typeof buttonVariants> & {
46
+ asChild?: boolean;
47
+ }) {
48
+ const Comp = asChild ? Slot : "button";
49
+
50
+ return (
51
+ <Comp
52
+ data-slot="button"
53
+ className={cn(buttonVariants({ variant, size, className }))}
54
+ {...props}
55
+ />
56
+ );
57
+ }
58
+
59
+ export { Button, buttonVariants };
@@ -0,0 +1,86 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "@aomi-labs/react";
4
+
5
+ const Card = React.forwardRef<
6
+ HTMLDivElement,
7
+ React.HTMLAttributes<HTMLDivElement>
8
+ >(({ className, ...props }, ref) => (
9
+ <div
10
+ ref={ref}
11
+ className={cn(
12
+ "bg-card text-card-foreground rounded-lg border shadow-sm",
13
+ className,
14
+ )}
15
+ {...props}
16
+ />
17
+ ));
18
+ Card.displayName = "Card";
19
+
20
+ const CardHeader = React.forwardRef<
21
+ HTMLDivElement,
22
+ React.HTMLAttributes<HTMLDivElement>
23
+ >(({ className, ...props }, ref) => (
24
+ <div
25
+ ref={ref}
26
+ className={cn("flex flex-col space-y-1.5 p-6", className)}
27
+ {...props}
28
+ />
29
+ ));
30
+ CardHeader.displayName = "CardHeader";
31
+
32
+ const CardTitle = React.forwardRef<
33
+ HTMLParagraphElement,
34
+ React.HTMLAttributes<HTMLHeadingElement>
35
+ >(({ className, ...props }, ref) => (
36
+ <h3
37
+ ref={ref}
38
+ className={cn(
39
+ "text-2xl font-semibold leading-none tracking-tight",
40
+ className,
41
+ )}
42
+ {...props}
43
+ />
44
+ ));
45
+ CardTitle.displayName = "CardTitle";
46
+
47
+ const CardDescription = React.forwardRef<
48
+ HTMLParagraphElement,
49
+ React.HTMLAttributes<HTMLParagraphElement>
50
+ >(({ className, ...props }, ref) => (
51
+ <p
52
+ ref={ref}
53
+ className={cn("text-muted-foreground text-sm", className)}
54
+ {...props}
55
+ />
56
+ ));
57
+ CardDescription.displayName = "CardDescription";
58
+
59
+ const CardContent = React.forwardRef<
60
+ HTMLDivElement,
61
+ React.HTMLAttributes<HTMLDivElement>
62
+ >(({ className, ...props }, ref) => (
63
+ <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
64
+ ));
65
+ CardContent.displayName = "CardContent";
66
+
67
+ const CardFooter = React.forwardRef<
68
+ HTMLDivElement,
69
+ React.HTMLAttributes<HTMLDivElement>
70
+ >(({ className, ...props }, ref) => (
71
+ <div
72
+ ref={ref}
73
+ className={cn("flex items-center p-6 pt-0", className)}
74
+ {...props}
75
+ />
76
+ ));
77
+ CardFooter.displayName = "CardFooter";
78
+
79
+ export {
80
+ Card,
81
+ CardHeader,
82
+ CardFooter,
83
+ CardTitle,
84
+ CardDescription,
85
+ CardContent,
86
+ };
@@ -0,0 +1,12 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
5
+
6
+ const Collapsible = CollapsiblePrimitive.Root;
7
+
8
+ const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
9
+
10
+ const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;
11
+
12
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent };