@aomi-labs/widget-lib 1.0.0 → 1.1.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 (76) hide show
  1. package/SHADCN-FETCH-GUIDE.md +105 -0
  2. package/components.json +10 -0
  3. package/dist/accordion.json +18 -0
  4. package/dist/alert.json +17 -0
  5. package/dist/aomi-frame.json +24 -0
  6. package/dist/assistant-thread-list.json +22 -0
  7. package/dist/assistant-thread.json +27 -0
  8. package/dist/assistant-threadlist-collapsible.json +23 -0
  9. package/dist/assistant-threadlist-sidebar.json +20 -0
  10. package/dist/assistant-tool-fallback.json +20 -0
  11. package/dist/avatar.json +17 -0
  12. package/dist/badge.json +17 -0
  13. package/dist/breadcrumb.json +17 -0
  14. package/dist/button.json +18 -0
  15. package/dist/card.json +15 -0
  16. package/dist/collapsible.json +17 -0
  17. package/dist/command.json +21 -0
  18. package/dist/dialog.json +18 -0
  19. package/dist/drawer.json +17 -0
  20. package/dist/input.json +15 -0
  21. package/dist/label.json +15 -0
  22. package/dist/notification.json +20 -0
  23. package/dist/popover.json +17 -0
  24. package/dist/registry.json +429 -0
  25. package/dist/separator.json +17 -0
  26. package/dist/sheet.json +18 -0
  27. package/dist/sidebar.json +18 -0
  28. package/dist/skeleton.json +15 -0
  29. package/dist/sonner.json +17 -0
  30. package/dist/tooltip.json +17 -0
  31. package/package.json +24 -88
  32. package/scripts/build-registry.js +74 -0
  33. package/src/components/aomi-frame.tsx +128 -0
  34. package/src/components/assistant-ui/attachment.tsx +235 -0
  35. package/src/components/assistant-ui/markdown-text.tsx +228 -0
  36. package/src/components/assistant-ui/thread-list.tsx +106 -0
  37. package/src/components/assistant-ui/thread.tsx +457 -0
  38. package/src/components/assistant-ui/threadlist-sidebar.tsx +71 -0
  39. package/src/components/assistant-ui/tool-fallback.tsx +48 -0
  40. package/src/components/assistant-ui/tooltip-icon-button.tsx +42 -0
  41. package/src/components/test/ThreadContextTest.tsx +204 -0
  42. package/src/components/tools/example-tool/ExampleTool.tsx +102 -0
  43. package/src/components/ui/accordion.tsx +58 -0
  44. package/src/components/ui/alert.tsx +62 -0
  45. package/src/components/ui/avatar.tsx +53 -0
  46. package/src/components/ui/badge.tsx +37 -0
  47. package/src/components/ui/breadcrumb.tsx +109 -0
  48. package/src/components/ui/button.tsx +59 -0
  49. package/src/components/ui/card.tsx +86 -0
  50. package/src/components/ui/collapsible.tsx +12 -0
  51. package/src/components/ui/command.tsx +156 -0
  52. package/src/components/ui/dialog.tsx +143 -0
  53. package/src/components/ui/drawer.tsx +118 -0
  54. package/src/components/ui/input.tsx +21 -0
  55. package/src/components/ui/label.tsx +20 -0
  56. package/src/components/ui/notification.tsx +57 -0
  57. package/src/components/ui/popover.tsx +33 -0
  58. package/src/components/ui/separator.tsx +28 -0
  59. package/src/components/ui/sheet.tsx +139 -0
  60. package/src/components/ui/sidebar.tsx +820 -0
  61. package/src/components/ui/skeleton.tsx +15 -0
  62. package/src/components/ui/sonner.tsx +29 -0
  63. package/src/components/ui/tooltip.tsx +61 -0
  64. package/src/hooks/use-mobile.ts +21 -0
  65. package/src/index.ts +26 -0
  66. package/src/registry.ts +218 -0
  67. package/{dist/styles.css → src/themes/default.css} +21 -3
  68. package/src/themes/tokens.config.ts +39 -0
  69. package/tsconfig.json +19 -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,105 @@
1
+ ⏺ After running npx shadcn add https://r.aomi.dev/aomi-frame.json:
2
+
3
+ File structure:
4
+ their-project/
5
+ ├── components.json ← their config (already exists)
6
+ ├── package.json ← npm deps added
7
+ ├── components/
8
+ │ ├── aomi-frame.tsx ← from r.aomi.dev
9
+ │ ├── assistant-ui/
10
+ │ │ ├── thread.tsx ← from r.aomi.dev
11
+ │ │ ├── thread-list.tsx ← from r.aomi.dev
12
+ │ │ ├── threadlist-sidebar.tsx ← from r.aomi.dev
13
+ │ │ ├── tool-fallback.tsx ← from r.aomi.dev
14
+ │ │ ├── markdown-text.tsx ← from r.assistant-ui.com
15
+ │ │ ├── tooltip-icon-button.tsx ← from r.assistant-ui.com
16
+ │ │ └── attachment.tsx ← from r.assistant-ui.com
17
+ │ └── ui/
18
+ │ ├── button.tsx ← from shadcn
19
+ │ ├── sidebar.tsx ← from shadcn
20
+ │ ├── separator.tsx ← from shadcn
21
+ │ ├── breadcrumb.tsx ← from shadcn
22
+ │ ├── skeleton.tsx ← from shadcn
23
+ │ ├── tooltip.tsx ← from shadcn
24
+ │ ├── dialog.tsx ← from shadcn
25
+ │ ├── avatar.tsx ← from shadcn
26
+ │ └── ...
27
+ └── lib/
28
+ └── utils.ts ← cn() helper (from shadcn init)
29
+
30
+ Their components.json (pre-existing, configured during npx shadcn init):
31
+ {
32
+ "$schema": "https://ui.shadcn.com/schema.json",
33
+ "style": "new-york",
34
+ "tailwind": {
35
+ "baseColor": "neutral",
36
+ "cssVariables": true
37
+ },
38
+ "aliases": {
39
+ "components": "@/components",
40
+ "utils": "@/lib/utils"
41
+ }
42
+ }
43
+
44
+ Their package.json gets these added:
45
+ {
46
+ "dependencies": {
47
+ "@aomi-labs/react": "^x.x.x",
48
+ "@assistant-ui/react": "^0.11.x",
49
+ "@assistant-ui/react-markdown": "^0.11.x",
50
+ "lucide-react": "^0.x.x",
51
+ "remark-gfm": "^4.x.x",
52
+ "@radix-ui/react-tooltip": "...",
53
+ "@radix-ui/react-dialog": "...",
54
+ ...
55
+ }
56
+ }
57
+
58
+ Usage in their code:
59
+ import { AomiFrame } from "@/components/aomi-frame";
60
+
61
+ export default function Page() {
62
+ return <AomiFrame />;
63
+ }
64
+
65
+ > when apps/registry/src/components/assistant-ui/thread-list.tsx says this:
66
+ > import {
67
+ > ThreadListItemPrimitive,
68
+ > ThreadListPrimitive,
69
+ > useAssistantState,
70
+ > } from "@assistant-ui/react";
71
+ > now my repo can resolve these dependencies thanks to correct pnpm configuration, but can the user
72
+ > application resolve it?
73
+
74
+ ⏺ Yes, because we list it in dependencies in the registry.
75
+
76
+ Looking at your registry.ts:
77
+
78
+ {
79
+ name: "assistant-thread-list",
80
+ file: "components/assistant-ui/thread-list.tsx",
81
+ dependencies: ["@assistant-ui/react", "lucide-react"], // ← This!
82
+ registryDependencies: [...],
83
+ }
84
+
85
+ What happens when user runs shadcn add:
86
+
87
+ 1. shadcn reads dependencies: ["@assistant-ui/react", "lucide-react"]
88
+ 2. Runs npm install @assistant-ui/react lucide-react
89
+ 3. Package is now in user's node_modules/
90
+ 4. Import resolves ✓
91
+
92
+ User's project:
93
+ ├── node_modules/
94
+ │ └── @assistant-ui/react/ ← installed by shadcn
95
+ ├── components/
96
+ │ └── assistant-ui/
97
+ │ └── thread-list.tsx ← import { ... } from "@assistant-ui/react" ✓
98
+
99
+ | Import type | Resolved via |
100
+ | ---------------------- | --------------------------------- |
101
+ | @assistant-ui/react | npm (installed from dependencies) |
102
+ | @/components/ui/button | Their components.json aliases |
103
+ | @aomi-labs/react | npm (installed from dependencies) |
104
+
105
+ So yes — as long as it's in the dependencies array, shadcn will install it for them.
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": true,
5
+ "tsx": true,
6
+ "aliases": {
7
+ "components": "@/components",
8
+ "utils": "@aomi-labs/react"
9
+ }
10
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "accordion",
4
+ "type": "registry:component",
5
+ "description": "A vertically stacked set of interactive headings that each reveal a section of content.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/accordion.tsx",
10
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@aomi-labs/react\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@radix-ui/react-accordion",
15
+ "lucide-react"
16
+ ],
17
+ "registryDependencies": []
18
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "alert",
4
+ "type": "registry:component",
5
+ "description": "Displays a callout for user attention.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/alert.tsx",
10
+ "content": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@aomi-labs/react\";\n\nconst alertVariants = cva(\n \"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\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n data-slot=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n data-slot=\"alert-title\"\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"alert-description\"\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "class-variance-authority"
15
+ ],
16
+ "registryDependencies": []
17
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "aomi-frame",
4
+ "type": "registry:component",
5
+ "description": "Full assistant shell with thread list and runtime wiring.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/aomi-frame.tsx",
10
+ "content": "\"use client\";\n\nimport { type CSSProperties, type ReactNode } from \"react\";\nimport {\n AomiRuntimeProvider,\n cn,\n useAomiRuntime,\n type UserConfig,\n} from \"@aomi-labs/react\";\nimport { Thread } from \"@/components/assistant-ui/thread\";\nimport { ThreadListSidebar } from \"@/components/assistant-ui/threadlist-sidebar\";\nimport {\n SidebarInset,\n SidebarProvider,\n SidebarTrigger,\n} from \"@/components/ui/sidebar\";\nimport { Separator } from \"@/components/ui/separator\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbList,\n BreadcrumbSeparator,\n} from \"@/components/ui/breadcrumb\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\ntype AomiFrameProps = {\n width?: CSSProperties[\"width\"];\n height?: CSSProperties[\"height\"];\n className?: string;\n style?: CSSProperties;\n /** Render prop for wallet footer - receives user state and setter from UserContext */\n walletFooter?: (props: UserConfig) => ReactNode;\n /** Additional content to render inside the frame */\n children?: ReactNode;\n};\n\n// =============================================================================\n// AomiFrame Component\n// =============================================================================\n\nexport const AomiFrame = ({\n width = \"100%\",\n height = \"80vh\",\n className,\n style,\n walletFooter,\n children,\n}: AomiFrameProps) => {\n const backendUrl =\n process.env.NEXT_PUBLIC_BACKEND_URL ?? \"http://localhost:8080\";\n\n return (\n <AomiRuntimeProvider backendUrl={backendUrl}>\n <AomiFrameShell\n width={width}\n height={height}\n className={className}\n style={style}\n walletFooter={walletFooter}\n >\n {children}\n </AomiFrameShell>\n </AomiRuntimeProvider>\n );\n};\n\n// =============================================================================\n// Internal Shell Component (uses hooks from providers)\n// =============================================================================\n\ntype AomiFrameShellProps = {\n width: CSSProperties[\"width\"];\n height: CSSProperties[\"height\"];\n className?: string;\n style?: CSSProperties;\n walletFooter?: (props: UserConfig) => ReactNode;\n children?: ReactNode;\n};\n\nconst AomiFrameShell = ({\n width,\n height,\n className,\n style,\n walletFooter,\n children,\n}: AomiFrameShellProps) => {\n const { user, setUser, currentThreadId, threadViewKey, getThreadMetadata } =\n useAomiRuntime();\n const currentTitle = getThreadMetadata(currentThreadId)?.title ?? \"New Chat\";\n\n const frameStyle: CSSProperties = { width, height, ...style };\n\n return (\n <SidebarProvider>\n {children}\n <div\n className={cn(\n \"flex h-full w-full overflow-hidden rounded-2xl bg-white shadow-2xl dark:bg-neutral-950\",\n className,\n )}\n style={frameStyle}\n >\n <ThreadListSidebar footer={walletFooter?.({ user, setUser })} />\n <SidebarInset className=\"relative\">\n <header className=\"mt-1 flex h-14 shrink-0 items-center gap-2 border-b px-3\">\n <SidebarTrigger />\n <Separator orientation=\"vertical\" className=\"mr-2 h-4\" />\n <Breadcrumb>\n <BreadcrumbList>\n <BreadcrumbItem className=\"hidden md:block\">\n {currentTitle}\n </BreadcrumbItem>\n <BreadcrumbSeparator className=\"hidden md:block\" />\n </BreadcrumbList>\n </Breadcrumb>\n </header>\n <div className=\"flex-1 overflow-hidden\">\n <Thread key={`${currentThreadId}-${threadViewKey}`} />\n </div>\n </SidebarInset>\n </div>\n </SidebarProvider>\n );\n};\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@aomi-labs/react"
15
+ ],
16
+ "registryDependencies": [
17
+ "https://widget.aomi.dev/r/assistant-thread.json",
18
+ "https://widget.aomi.dev/r/assistant-threadlist-sidebar.json",
19
+ "https://widget.aomi.dev/r/notification.json",
20
+ "separator",
21
+ "breadcrumb",
22
+ "sidebar"
23
+ ]
24
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "assistant-thread-list",
4
+ "type": "registry:component",
5
+ "description": "Thread list wrapper wired to runtime adapter.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/assistant-ui/thread-list.tsx",
10
+ "content": "\"use client\";\n\nimport type { FC } from \"react\";\nimport {\n ThreadListItemPrimitive,\n ThreadListPrimitive,\n useAssistantState,\n} from \"@assistant-ui/react\";\nimport { PlusIcon, TrashIcon } from \"lucide-react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { TooltipIconButton } from \"@/components/assistant-ui/tooltip-icon-button\";\nimport { Skeleton } from \"@/components/ui/skeleton\";\n\nexport const ThreadList: FC = () => {\n return (\n <ThreadListPrimitive.Root className=\"aui-root aui-thread-list-root flex flex-col items-stretch gap-1.5\">\n <ThreadListNew />\n <ThreadListItems />\n </ThreadListPrimitive.Root>\n );\n};\n\nconst ThreadListNew: FC = () => {\n return (\n <ThreadListPrimitive.New asChild>\n <Button\n className=\"aui-thread-list-new hover:bg-muted data-active:bg-muted flex items-center justify-start gap-1 rounded-lg px-2.5 py-2 text-start\"\n variant=\"ghost\"\n >\n <PlusIcon />\n New Chat\n </Button>\n </ThreadListPrimitive.New>\n );\n};\n\nconst ThreadListItems: FC = () => {\n const isLoading = useAssistantState(({ threads }) => threads.isLoading);\n\n if (isLoading) {\n return <ThreadListSkeleton />;\n }\n\n return <ThreadListPrimitive.Items components={{ ThreadListItem }} />;\n};\n\nconst ThreadListSkeleton: FC = () => {\n return (\n <>\n {Array.from({ length: 5 }, (_, i) => (\n <div\n key={i}\n role=\"status\"\n aria-label=\"Loading threads\"\n aria-live=\"polite\"\n className=\"aui-thread-list-skeleton-wrapper flex items-center gap-2 rounded-md px-3 py-2\"\n >\n <Skeleton className=\"aui-thread-list-skeleton h-[22px] flex-grow\" />\n </div>\n ))}\n </>\n );\n};\n\nconst ThreadListItem: FC = () => {\n return (\n <ThreadListItemPrimitive.Root className=\"aui-thread-list-item hover:bg-muted focus-visible:bg-muted focus-visible:ring-ring data-active:bg-muted flex items-center gap-2 rounded-lg transition-all focus-visible:outline-none focus-visible:ring-2\">\n <ThreadListItemPrimitive.Trigger className=\"aui-thread-list-item-trigger flex-grow px-3 py-2 text-start\">\n <ThreadListItemTitle />\n </ThreadListItemPrimitive.Trigger>\n <ThreadListItemDelete />\n </ThreadListItemPrimitive.Root>\n );\n};\n\nconst ThreadListItemTitle: FC = () => {\n return (\n <span className=\"aui-thread-list-item-title text-sm\">\n <ThreadListItemPrimitive.Title fallback=\"New Chat\" />\n </span>\n );\n};\n\nconst ThreadListItemDelete: FC = () => {\n return (\n <ThreadListItemPrimitive.Delete asChild>\n <TooltipIconButton\n className=\"aui-thread-list-item-delete text-foreground hover:text-primary ml-auto mr-3 size-4 p-0\"\n variant=\"ghost\"\n tooltip=\"Delete thread\"\n onClick={(event) => {\n const confirmed = window.confirm(\n \"Delete this chat? This action cannot be undone.\",\n );\n if (!confirmed) {\n event.preventDefault();\n event.stopPropagation();\n }\n }}\n >\n <TrashIcon />\n </TooltipIconButton>\n </ThreadListItemPrimitive.Delete>\n );\n};\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@assistant-ui/react",
15
+ "lucide-react"
16
+ ],
17
+ "registryDependencies": [
18
+ "https://r.assistant-ui.com/tooltip-icon-button.json",
19
+ "button",
20
+ "skeleton"
21
+ ]
22
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "assistant-thread",
4
+ "type": "registry:component",
5
+ "description": "Chat surface built on @assistant-ui primitives.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/assistant-ui/thread.tsx",
10
+ "content": "\"use client\";\n\nimport {\n ArrowDownIcon,\n ArrowUpIcon,\n CheckIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n CopyIcon,\n PencilIcon,\n RefreshCwIcon,\n Square,\n} from \"lucide-react\";\n\nimport {\n ActionBarPrimitive,\n BranchPickerPrimitive,\n ComposerPrimitive,\n ErrorPrimitive,\n MessagePrimitive,\n ThreadPrimitive,\n} from \"@assistant-ui/react\";\n\nimport type { FC } from \"react\";\nimport { useEffect } from \"react\";\nimport { LazyMotion, MotionConfig, domAnimation } from \"motion/react\";\nimport * as m from \"motion/react-m\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { MarkdownText } from \"@/components/assistant-ui/markdown-text\";\nimport { ToolFallback } from \"@/components/assistant-ui/tool-fallback\";\nimport { TooltipIconButton } from \"@/components/assistant-ui/tooltip-icon-button\";\nimport {\n ComposerAddAttachment,\n ComposerAttachments,\n UserMessageAttachments,\n} from \"@/components/assistant-ui/attachment\";\n\nimport { cn, useNotification, useThreadContext } from \"@aomi-labs/react\";\nimport { useAssistantApi, useMessage } from \"@assistant-ui/react\";\n\nconst seenSystemMessages = new Set<string>();\n\nexport const Thread: FC = () => {\n const api = useAssistantApi();\n const { threadViewKey } = useThreadContext();\n\n useEffect(() => {\n try {\n const composer = api.composer();\n composer.setText(\"\");\n void composer.clearAttachments?.();\n } catch (error) {\n console.error(\"Failed to reset composer input:\", error);\n }\n }, [api, threadViewKey]);\n\n return (\n <LazyMotion features={domAnimation}>\n <MotionConfig reducedMotion=\"user\">\n <ThreadPrimitive.Root\n className=\"aui-root aui-thread-root @container bg-background flex h-full flex-col\"\n style={{\n [\"--thread-max-width\" as string]: \"44rem\",\n }}\n >\n <ThreadPrimitive.Viewport className=\"aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll px-4\">\n <ThreadPrimitive.If empty>\n <ThreadWelcome />\n </ThreadPrimitive.If>\n\n <ThreadPrimitive.Messages\n components={{\n UserMessage,\n EditComposer,\n AssistantMessage,\n SystemMessage,\n }}\n />\n\n <ThreadPrimitive.If empty={false}>\n <div className=\"aui-thread-viewport-spacer min-h-8 grow\" />\n </ThreadPrimitive.If>\n\n <Composer />\n </ThreadPrimitive.Viewport>\n </ThreadPrimitive.Root>\n </MotionConfig>\n </LazyMotion>\n );\n};\n\nconst ThreadScrollToBottom: FC = () => {\n return (\n <ThreadPrimitive.ScrollToBottom asChild>\n <TooltipIconButton\n tooltip=\"Scroll to bottom\"\n variant=\"outline\"\n className=\"aui-thread-scroll-to-bottom dark:bg-background dark:hover:bg-accent absolute -top-12 z-10 self-center rounded-full p-4 disabled:invisible\"\n >\n <ArrowDownIcon />\n </TooltipIconButton>\n </ThreadPrimitive.ScrollToBottom>\n );\n};\n\nconst ThreadWelcome: FC = () => {\n return (\n <div className=\"aui-thread-welcome-root mx-auto my-auto flex w-full max-w-[var(--thread-max-width)] flex-grow flex-col\">\n <div className=\"aui-thread-welcome-center flex w-full flex-grow flex-col items-center justify-center\">\n <div className=\"aui-thread-welcome-message flex size-full flex-col justify-center px-8\">\n <m.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 10 }}\n className=\"aui-thread-welcome-message-motion-1 text-2xl font-semibold\"\n >\n Hello there!\n </m.div>\n <m.div\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 10 }}\n transition={{ delay: 0.1 }}\n className=\"aui-thread-welcome-message-motion-2 text-muted-foreground/65 text-2xl\"\n >\n How can I help you today?\n </m.div>\n </div>\n </div>\n <ThreadSuggestions />\n </div>\n );\n};\n\nconst ThreadSuggestions: FC = () => {\n return (\n <div className=\"aui-thread-welcome-suggestions @md:grid-cols-2 grid w-full gap-2 pb-4\">\n {[\n {\n title: \"Show my wallet balances\",\n label: \"and positions\",\n action: \"Show my wallet balances and positions\",\n },\n {\n title: \"Swap 1 ETH to USDC\",\n label: \"with the best price\",\n action: \"Swap 1 ETH to USDC with the best price\",\n },\n {\n title: \"Stake half of my ETH\",\n label: \"in the highest yield pool\",\n action: \"Stake half of my ETH in the highest yield pool\",\n },\n {\n title: \"Bridge 100 USDC\",\n label: \"from Ethereum to Arbitrum\",\n action: \"Bridge 100 USDC from Ethereum to Arbitrum\",\n },\n ].map((suggestedAction, index) => (\n <m.div\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 20 }}\n transition={{ delay: 0.05 * index }}\n key={`suggested-action-${suggestedAction.title}-${index}`}\n className=\"aui-thread-welcome-suggestion-display @md:[&:nth-child(n+3)]:block [&:nth-child(n+3)]:hidden\"\n >\n <ThreadPrimitive.Suggestion\n prompt={suggestedAction.action}\n send\n asChild\n >\n <Button\n variant=\"ghost\"\n className=\"aui-thread-welcome-suggestion @md:flex-col dark:hover:bg-accent/60 h-auto w-full flex-1 flex-wrap items-start justify-start gap-1 rounded-3xl border px-5 py-4 text-left text-sm\"\n aria-label={suggestedAction.action}\n >\n <span className=\"aui-thread-welcome-suggestion-text-1 font-medium\">\n {suggestedAction.title}\n </span>\n <span className=\"aui-thread-welcome-suggestion-text-2 text-muted-foreground\">\n {suggestedAction.label}\n </span>\n </Button>\n </ThreadPrimitive.Suggestion>\n </m.div>\n ))}\n </div>\n );\n};\n\nconst Composer: FC = () => {\n return (\n <div className=\"aui-composer-wrapper bg-background sticky bottom-0 mx-auto flex w-full max-w-[var(--thread-max-width)] flex-col gap-4 overflow-visible rounded-t-3xl pb-4 md:pb-6\">\n <ThreadScrollToBottom />\n <ComposerPrimitive.Root className=\"aui-composer-root rounded-4xl dark:border-muted-foreground/15 relative flex w-full flex-col border bg-white px-1 pt-2 shadow-[0_9px_9px_0px_rgba(0,0,0,0.01),0_2px_5px_0px_rgba(0,0,0,0.06)]\">\n <ComposerAttachments />\n <ComposerPrimitive.Input\n placeholder=\"Send a message...\"\n className=\"aui-composer-input placeholder:text-muted-foreground focus:outline-primary ml-3 mt-2 max-h-32 min-h-16 w-full resize-none bg-transparent px-3.5 pb-3 pt-1.5 text-sm text-stone-800 outline-none\"\n rows={1}\n autoFocus\n aria-label=\"Message input\"\n />\n <ComposerAction />\n </ComposerPrimitive.Root>\n </div>\n );\n};\n\nconst ComposerAction: FC = () => {\n return (\n <div className=\"aui-composer-action-wrapper relative mx-1 mb-2 mt-2 flex items-center justify-between\">\n <ComposerAddAttachment />\n\n <ThreadPrimitive.If running={false}>\n <ComposerPrimitive.Send asChild>\n <TooltipIconButton\n tooltip=\"Send message\"\n side=\"bottom\"\n type=\"submit\"\n variant=\"default\"\n size=\"icon\"\n className=\"aui-composer-send mb-3 mr-3 size-[34px] rounded-full p-1\"\n aria-label=\"Send message\"\n >\n <ArrowUpIcon className=\"aui-composer-send-icon size-5\" />\n </TooltipIconButton>\n </ComposerPrimitive.Send>\n </ThreadPrimitive.If>\n\n <ThreadPrimitive.If running>\n <ComposerPrimitive.Cancel asChild>\n <Button\n type=\"button\"\n variant=\"default\"\n size=\"icon\"\n className=\"aui-composer-cancel border-muted-foreground/60 hover:bg-primary/75 dark:border-muted-foreground/90 size-[34px] rounded-full border\"\n aria-label=\"Stop generating\"\n >\n <Square className=\"aui-composer-cancel-icon size-3.5 fill-white dark:fill-black\" />\n </Button>\n </ComposerPrimitive.Cancel>\n </ThreadPrimitive.If>\n </div>\n );\n};\n\nconst MessageError: FC = () => {\n return (\n <MessagePrimitive.Error>\n <ErrorPrimitive.Root className=\"aui-message-error-root border-destructive bg-destructive/10 text-destructive dark:bg-destructive/5 mt-2 rounded-md border p-3 text-sm dark:text-red-200\">\n <ErrorPrimitive.Message className=\"aui-message-error-message line-clamp-2\" />\n </ErrorPrimitive.Root>\n </MessagePrimitive.Error>\n );\n};\n\nconst AssistantMessage: FC = () => {\n return (\n <MessagePrimitive.Root asChild>\n <div\n className=\"aui-assistant-message-root animate-in fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-[var(--thread-max-width)] py-4 duration-150 ease-out last:mb-24\"\n data-role=\"assistant\"\n >\n <div className=\"aui-assistant-message-content text-foreground mx-2 break-words text-sm leading-5\">\n <MessagePrimitive.Parts\n components={{\n Text: MarkdownText,\n tools: { Fallback: ToolFallback },\n }}\n />\n <MessageError />\n </div>\n\n <div className=\"aui-assistant-message-footer ml-2 mt-2 flex\">\n <BranchPicker />\n <AssistantActionBar />\n </div>\n </div>\n </MessagePrimitive.Root>\n );\n};\n\nconst AssistantActionBar: FC = () => {\n return (\n <ActionBarPrimitive.Root\n hideWhenRunning\n autohide=\"not-last\"\n autohideFloat=\"single-branch\"\n className=\"aui-assistant-action-bar-root text-muted-foreground data-floating:absolute data-floating:rounded-md data-floating:border data-floating:bg-background data-floating:p-1 data-floating:shadow-sm col-start-3 row-start-2 -ml-1 flex gap-1\"\n >\n <ActionBarPrimitive.Copy asChild>\n <TooltipIconButton tooltip=\"Copy\">\n <MessagePrimitive.If copied>\n <CheckIcon />\n </MessagePrimitive.If>\n <MessagePrimitive.If copied={false}>\n <CopyIcon />\n </MessagePrimitive.If>\n </TooltipIconButton>\n </ActionBarPrimitive.Copy>\n <ActionBarPrimitive.Reload asChild>\n <TooltipIconButton tooltip=\"Refresh\">\n <RefreshCwIcon />\n </TooltipIconButton>\n </ActionBarPrimitive.Reload>\n </ActionBarPrimitive.Root>\n );\n};\n\nconst UserMessage: FC = () => {\n return (\n <MessagePrimitive.Root asChild>\n <div\n className=\"aui-user-message-root animate-in fade-in slide-in-from-bottom-1 mx-auto grid w-full max-w-[var(--thread-max-width)] auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 px-2 py-4 duration-150 ease-out first:mt-3 last:mb-5 [&:where(>*)]:col-start-2\"\n data-role=\"user\"\n >\n <UserMessageAttachments />\n\n <div className=\"aui-user-message-content-wrapper relative col-start-2 min-w-0\">\n <div className=\"aui-user-message-content bg-muted text-foreground break-words rounded-3xl px-5 py-2.5 text-sm\">\n <MessagePrimitive.Parts />\n </div>\n <div className=\"aui-user-action-bar-wrapper absolute left-0 top-1/2 -translate-x-full -translate-y-1/2 pr-2\">\n <UserActionBar />\n </div>\n </div>\n\n <BranchPicker className=\"aui-user-branch-picker col-span-full col-start-1 row-start-3 -mr-1 justify-end\" />\n </div>\n </MessagePrimitive.Root>\n );\n};\n\nconst UserActionBar: FC = () => {\n return (\n <ActionBarPrimitive.Root\n hideWhenRunning\n autohide=\"not-last\"\n className=\"aui-user-action-bar-root flex flex-col items-end\"\n >\n <ActionBarPrimitive.Edit asChild>\n <TooltipIconButton tooltip=\"Edit\" className=\"aui-user-action-edit p-4\">\n <PencilIcon />\n </TooltipIconButton>\n </ActionBarPrimitive.Edit>\n </ActionBarPrimitive.Root>\n );\n};\n\nconst EditComposer: FC = () => {\n return (\n <div className=\"aui-edit-composer-wrapper mx-auto flex w-full max-w-[var(--thread-max-width)] flex-col gap-4 px-2 first:mt-4\">\n <ComposerPrimitive.Root className=\"aui-edit-composer-root max-w-7/8 bg-muted ml-auto flex w-full flex-col rounded-xl\">\n <ComposerPrimitive.Input\n className=\"aui-edit-composer-input text-foreground flex min-h-[60px] w-full resize-none bg-transparent p-4 outline-none\"\n autoFocus\n />\n\n <div className=\"aui-edit-composer-footer mx-3 mb-3 flex items-center justify-center gap-2 self-end\">\n <ComposerPrimitive.Cancel asChild>\n <Button variant=\"ghost\" size=\"sm\" aria-label=\"Cancel edit\">\n Cancel\n </Button>\n </ComposerPrimitive.Cancel>\n <ComposerPrimitive.Send asChild>\n <Button size=\"sm\" aria-label=\"Update message\">\n Update\n </Button>\n </ComposerPrimitive.Send>\n </div>\n </ComposerPrimitive.Root>\n </div>\n );\n};\n\nconst BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({\n className,\n ...rest\n}) => {\n return (\n <BranchPickerPrimitive.Root\n hideWhenSingleBranch\n className={cn(\n \"aui-branch-picker-root text-muted-foreground -ml-2 mr-2 inline-flex items-center text-xs\",\n className,\n )}\n {...rest}\n >\n <BranchPickerPrimitive.Previous asChild>\n <TooltipIconButton tooltip=\"Previous\">\n <ChevronLeftIcon />\n </TooltipIconButton>\n </BranchPickerPrimitive.Previous>\n <span className=\"aui-branch-picker-state font-medium\">\n <BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />\n </span>\n <BranchPickerPrimitive.Next asChild>\n <TooltipIconButton tooltip=\"Next\">\n <ChevronRightIcon />\n </TooltipIconButton>\n </BranchPickerPrimitive.Next>\n </BranchPickerPrimitive.Root>\n );\n};\n\nconst SystemMessage: FC = () => {\n const { showNotification } = useNotification();\n const messageId = useMessage((state) => state.id);\n const content = useMessage((state) => state.content) as Array<{\n type: string;\n text?: string;\n }>;\n const custom = useMessage((state) => state.metadata?.custom) as\n | { kind?: string; title?: string }\n | undefined;\n useEffect(() => {\n const text = content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text ?? \"\")\n .join(\"\")\n .trim();\n\n if (!text) return;\n\n const key = messageId ?? text;\n if (seenSystemMessages.has(key)) return;\n seenSystemMessages.add(key);\n\n const inferredKind =\n custom?.kind ??\n (text.startsWith(\"Wallet transaction request:\")\n ? \"wallet_tx_request\"\n : \"system_notice\");\n\n const type =\n inferredKind === \"system_error\"\n ? \"error\"\n : inferredKind === \"system_success\"\n ? \"success\"\n : \"notice\";\n\n const title =\n custom?.title ??\n (inferredKind === \"wallet_tx_request\"\n ? \"Wallet transaction request\"\n : inferredKind === \"system_error\"\n ? \"Error\"\n : \"System notice\");\n\n showNotification({ type, title, message: text });\n }, [content, custom, showNotification, messageId]);\n\n return null;\n};\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@aomi-labs/react",
15
+ "@assistant-ui/react",
16
+ "@assistant-ui/react-markdown",
17
+ "lucide-react",
18
+ "remark-gfm"
19
+ ],
20
+ "registryDependencies": [
21
+ "https://r.assistant-ui.com/markdown-text.json",
22
+ "https://r.assistant-ui.com/tooltip-icon-button.json",
23
+ "https://r.assistant-ui.com/attachment.json",
24
+ "https://widget.aomi.dev/r/assistant-tool-fallback.json",
25
+ "button"
26
+ ]
27
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "assistant-threadlist-collapsible",
4
+ "type": "registry:component",
5
+ "description": "Collapsible shell for thread navigation and wallet footer slot.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/assistant-ui/threadlist-collapsible.tsx",
10
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { MenuIcon } from \"lucide-react\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { Button } from \"@/components/ui/button\";\nimport { ThreadList } from \"@/components/assistant-ui/thread-list\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { cn } from \"@aomi-labs/react\";\n\ntype ThreadListCollapsibleProps = {\n /** Optional footer component (e.g., WalletFooter from consumer app) */\n footer?: React.ReactNode;\n /** Default open state */\n defaultOpen?: boolean;\n /** Controlled open state */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Additional className */\n className?: string;\n};\n\nexport function ThreadListCollapsible({\n footer,\n defaultOpen = false,\n open,\n onOpenChange,\n className,\n}: ThreadListCollapsibleProps) {\n const [isOpen, setIsOpen] = React.useState(defaultOpen);\n\n const handleOpenChange = React.useCallback(\n (newOpen: boolean) => {\n if (onOpenChange) {\n onOpenChange(newOpen);\n } else {\n setIsOpen(newOpen);\n }\n },\n [onOpenChange]\n );\n\n const isControlled = open !== undefined;\n const collapsibleOpen = isControlled ? open : isOpen;\n\n return (\n <div\n className={cn(\n \"flex flex-col border-r bg-background transition-all duration-200\",\n collapsibleOpen ? \"w-64\" : \"w-16\",\n className\n )}\n >\n <Collapsible\n open={collapsibleOpen}\n onOpenChange={handleOpenChange}\n className=\"flex flex-1 flex-col overflow-hidden\"\n >\n {/* Header */}\n <div className=\"aomi-collapsible-header flex h-14 shrink-0 items-center gap-2 border-b px-3\">\n <div className=\"flex items-center justify-between gap-2 w-full\">\n <CollapsibleTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"shrink-0\"\n aria-label={collapsibleOpen ? \"Collapse sidebar\" : \"Expand sidebar\"}\n >\n <MenuIcon className=\"size-5\" />\n </Button>\n </CollapsibleTrigger>\n\n {collapsibleOpen && (\n <Link\n href=\"https://aomi.dev\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-2 rounded-md px-2 py-1.5 hover:bg-accent transition-colors\"\n >\n <div className=\"aomi-collapsible-header-icon-wrapper flex aspect-square size-8 items-center justify-center rounded-lg bg-white\">\n <Image\n src=\"/assets/images/a.svg\"\n alt=\"Aomi Logo\"\n width={28}\n height={28}\n className=\"aomi-collapsible-header-icon size-7 ml-3\"\n priority\n />\n </div>\n </Link>\n )}\n </div>\n </div>\n\n {/* Collapsible Content */}\n <CollapsibleContent className=\"flex flex-1 flex-col overflow-hidden data-[state=closed]:hidden\">\n <div className=\"aomi-collapsible-content flex flex-1 flex-col overflow-hidden p-2\">\n <ThreadList />\n </div>\n {footer && (\n <>\n <Separator />\n <div className=\"aomi-collapsible-footer border-t border-sm py-4 px-2\">\n {footer}\n </div>\n </>\n )}\n </CollapsibleContent>\n </Collapsible>\n </div>\n );\n}\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "lucide-react",
15
+ "next"
16
+ ],
17
+ "registryDependencies": [
18
+ "https://widget.aomi.dev/r/assistant-thread-list.json",
19
+ "collapsible",
20
+ "button",
21
+ "separator"
22
+ ]
23
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "assistant-threadlist-sidebar",
4
+ "type": "registry:component",
5
+ "description": "Sidebar shell for thread navigation and wallet footer slot.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/assistant-ui/threadlist-sidebar.tsx",
10
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport {\n Sidebar,\n SidebarContent,\n SidebarFooter,\n SidebarHeader,\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarRail,\n} from \"@/components/ui/sidebar\";\nimport { ThreadList } from \"@/components/assistant-ui/thread-list\";\n\ntype ThreadListSidebarProps = React.ComponentProps<typeof Sidebar> & {\n /** Optional footer component (e.g., WalletFooter from consumer app) */\n footer?: React.ReactNode;\n};\n\nexport function ThreadListSidebar({\n footer,\n ...props\n}: ThreadListSidebarProps) {\n return (\n <Sidebar\n collapsible=\"offcanvas\"\n variant=\"inset\"\n className=\"relative\"\n {...props}\n >\n <SidebarHeader className=\"aomi-sidebar-header\">\n <div className=\"aomi-sidebar-header-content flex items-center justify-between\">\n <SidebarMenu>\n <SidebarMenuItem>\n <SidebarMenuButton size=\"lg\" asChild>\n <Link\n href=\"https://aomi.dev\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <div className=\"aomi-sidebar-header-icon-wrapper flex aspect-square size-8 items-center justify-center rounded-lg bg-white\">\n <Image\n src=\"/assets/images/bubble.svg\"\n alt=\"Logo\"\n width={28}\n height={28}\n className=\"aomi-sidebar-header-icon ml-3 size-7\"\n priority\n />\n </div>\n </Link>\n </SidebarMenuButton>\n </SidebarMenuItem>\n </SidebarMenu>\n </div>\n </SidebarHeader>\n <SidebarContent className=\"aomi-sidebar-content\">\n <ThreadList />\n </SidebarContent>\n <SidebarRail />\n {footer && (\n <SidebarFooter className=\"aomi-sidebar-footer border-sm border-t py-4\">\n {footer}\n </SidebarFooter>\n )}\n </Sidebar>\n );\n}\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "lucide-react"
15
+ ],
16
+ "registryDependencies": [
17
+ "https://widget.aomi.dev/r/assistant-thread-list.json",
18
+ "sidebar"
19
+ ]
20
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "assistant-tool-fallback",
4
+ "type": "registry:component",
5
+ "description": "Fallback renderer for assistant tool calls.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/assistant-ui/tool-fallback.tsx",
10
+ "content": "\"use client\";\n\nimport type { ToolCallMessagePartComponent } from \"@assistant-ui/react\";\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\n\nexport const ToolFallback: ToolCallMessagePartComponent = ({\n toolName,\n argsText,\n result,\n}) => {\n const [isCollapsed, setIsCollapsed] = useState(true);\n return (\n <div className=\"aui-tool-fallback-root mb-4 flex w-full flex-col gap-3 rounded-lg border py-3\">\n <div className=\"aui-tool-fallback-header flex items-center gap-2 px-4\">\n <CheckIcon className=\"aui-tool-fallback-icon size-4\" />\n <p className=\"aui-tool-fallback-title flex-grow\">\n Used tool: <b>{toolName}</b>\n </p>\n <Button onClick={() => setIsCollapsed(!isCollapsed)}>\n {isCollapsed ? <ChevronUpIcon /> : <ChevronDownIcon />}\n </Button>\n </div>\n {!isCollapsed && (\n <div className=\"aui-tool-fallback-content bg-muted flex flex-col gap-2 border-t pt-2\">\n <div className=\"aui-tool-fallback-args-root px-4\">\n <pre className=\"aui-tool-fallback-args-value whitespace-pre-wrap\">\n {argsText}\n </pre>\n </div>\n {result !== undefined && (\n <div className=\"aui-tool-fallback-result-root border-t border-dashed px-4 pt-2\">\n <p className=\"aui-tool-fallback-result-header font-semibold\">\n Result:\n </p>\n <pre className=\"aui-tool-fallback-result-content whitespace-pre-wrap text-[012px]\">\n {typeof result === \"string\"\n ? result\n : JSON.stringify(result, null, 2)}\n </pre>\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@assistant-ui/react",
15
+ "lucide-react"
16
+ ],
17
+ "registryDependencies": [
18
+ "button"
19
+ ]
20
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "avatar",
4
+ "type": "registry:component",
5
+ "description": "An image element with a fallback for representing the user.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/avatar.tsx",
10
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\";\n\nimport { cn } from \"@aomi-labs/react\";\n\nfunction Avatar({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\n \"relative flex size-8 shrink-0 overflow-hidden rounded-full\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full\", className)}\n {...props}\n />\n );\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"bg-muted flex size-full items-center justify-center rounded-full\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Avatar, AvatarImage, AvatarFallback };\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@radix-ui/react-avatar"
15
+ ],
16
+ "registryDependencies": []
17
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "badge",
4
+ "type": "registry:component",
5
+ "description": "Displays a badge or a component that looks like a badge.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/badge.tsx",
10
+ "content": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@aomi-labs/react\";\n\nconst badgeVariants = cva(\n \"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\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground hover:bg-primary/80\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n destructive:\n \"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80\",\n outline: \"text-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nexport interface BadgeProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant }), className)} {...props} />\n );\n}\n\nexport { Badge, badgeVariants };\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "class-variance-authority"
15
+ ],
16
+ "registryDependencies": []
17
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "breadcrumb",
4
+ "type": "registry:component",
5
+ "description": "Displays the path to the current resource using a hierarchy of links.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/breadcrumb.tsx",
10
+ "content": "import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { ChevronRight, MoreHorizontal } from \"lucide-react\";\n\nimport { cn } from \"@aomi-labs/react\";\n\nfunction Breadcrumb({ ...props }: React.ComponentProps<\"nav\">) {\n return <nav aria-label=\"breadcrumb\" data-slot=\"breadcrumb\" {...props} />;\n}\n\nfunction BreadcrumbList({ className, ...props }: React.ComponentProps<\"ol\">) {\n return (\n <ol\n data-slot=\"breadcrumb-list\"\n className={cn(\n \"text-muted-foreground flex flex-wrap items-center gap-1.5 break-words text-sm sm:gap-2.5\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction BreadcrumbItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"breadcrumb-item\"\n className={cn(\"inline-flex items-center gap-1.5\", className)}\n {...props}\n />\n );\n}\n\nfunction BreadcrumbLink({\n asChild,\n className,\n ...props\n}: React.ComponentProps<\"a\"> & {\n asChild?: boolean;\n}) {\n const Comp = asChild ? Slot : \"a\";\n\n return (\n <Comp\n data-slot=\"breadcrumb-link\"\n className={cn(\"hover:text-foreground transition-colors\", className)}\n {...props}\n />\n );\n}\n\nfunction BreadcrumbPage({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"breadcrumb-page\"\n role=\"link\"\n aria-disabled=\"true\"\n aria-current=\"page\"\n className={cn(\"text-foreground font-normal\", className)}\n {...props}\n />\n );\n}\n\nfunction BreadcrumbSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"breadcrumb-separator\"\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"[&>svg]:size-3.5\", className)}\n {...props}\n >\n {children ?? <ChevronRight />}\n </li>\n );\n}\n\nfunction BreadcrumbEllipsis({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"breadcrumb-ellipsis\"\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"flex size-9 items-center justify-center\", className)}\n {...props}\n >\n <MoreHorizontal className=\"size-4\" />\n <span className=\"sr-only\">More</span>\n </span>\n );\n}\n\nexport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n};\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@radix-ui/react-slot"
15
+ ],
16
+ "registryDependencies": []
17
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "button",
4
+ "type": "registry:component",
5
+ "description": "Displays a button or a component that looks like a button.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/button.tsx",
10
+ "content": "import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@aomi-labs/react\";\n\nconst buttonVariants = cva(\n \"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\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"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\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n }) {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@radix-ui/react-slot",
15
+ "class-variance-authority"
16
+ ],
17
+ "registryDependencies": []
18
+ }
package/dist/card.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "card",
4
+ "type": "registry:component",
5
+ "description": "Displays a card with header, content, and footer.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/card.tsx",
10
+ "content": "import * as React from \"react\";\n\nimport { cn } from \"@aomi-labs/react\";\n\nconst Card = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"bg-card text-card-foreground rounded-lg border shadow-sm\",\n className,\n )}\n {...props}\n />\n));\nCard.displayName = \"Card\";\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"flex flex-col space-y-1.5 p-6\", className)}\n {...props}\n />\n));\nCardHeader.displayName = \"CardHeader\";\n\nconst CardTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h3\n ref={ref}\n className={cn(\n \"text-2xl font-semibold leading-none tracking-tight\",\n className,\n )}\n {...props}\n />\n));\nCardTitle.displayName = \"CardTitle\";\n\nconst CardDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n));\nCardDescription.displayName = \"CardDescription\";\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"p-6 pt-0\", className)} {...props} />\n));\nCardContent.displayName = \"CardContent\";\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"flex items-center p-6 pt-0\", className)}\n {...props}\n />\n));\nCardFooter.displayName = \"CardFooter\";\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardDescription,\n CardContent,\n};\n"
11
+ }
12
+ ],
13
+ "dependencies": [],
14
+ "registryDependencies": []
15
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "collapsible",
4
+ "type": "registry:component",
5
+ "description": "An interactive component which expands/collapses a panel.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/collapsible.tsx",
10
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\";\n\nconst Collapsible = CollapsiblePrimitive.Root;\n\nconst CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;\n\nconst CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent };\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@radix-ui/react-collapsible"
15
+ ],
16
+ "registryDependencies": []
17
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "command",
4
+ "type": "registry:component",
5
+ "description": "Fast, composable, unstyled command menu for React.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/command.tsx",
10
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { type DialogProps } from \"@radix-ui/react-dialog\";\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport { Search } from \"lucide-react\";\n\nimport { cn } from \"@aomi-labs/react\";\nimport { Dialog, DialogContent } from \"./dialog\";\n\nconst Command = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive\n ref={ref}\n className={cn(\n \"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md\",\n className,\n )}\n {...props}\n />\n));\nCommand.displayName = CommandPrimitive.displayName;\n\ninterface CommandDialogProps extends DialogProps {}\n\nconst CommandDialog = ({ children, ...props }: CommandDialogProps) => {\n return (\n <Dialog {...props}>\n <DialogContent className=\"overflow-hidden p-0 shadow-lg\">\n <Command className=\"[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[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\">\n {children}\n </Command>\n </DialogContent>\n </Dialog>\n );\n};\n\nconst CommandInput = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Input>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>\n>(({ className, ...props }, ref) => (\n // eslint-disable-next-line react/no-unknown-property\n <div className=\"flex items-center border-b px-3\" cmdk-input-wrapper=\"\">\n <Search className=\"mr-2 h-4 w-4 shrink-0 opacity-50\" />\n <CommandPrimitive.Input\n ref={ref}\n className={cn(\n \"placeholder:text-muted-foreground flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n </div>\n));\n\nCommandInput.displayName = CommandPrimitive.Input.displayName;\n\nconst CommandList = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.List\n ref={ref}\n className={cn(\"max-h-[300px] overflow-y-auto overflow-x-hidden\", className)}\n {...props}\n />\n));\n\nCommandList.displayName = CommandPrimitive.List.displayName;\n\nconst CommandEmpty = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Empty>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>\n>((props, ref) => (\n <CommandPrimitive.Empty\n ref={ref}\n className=\"py-6 text-center text-sm\"\n {...props}\n />\n));\n\nCommandEmpty.displayName = CommandPrimitive.Empty.displayName;\n\nconst CommandGroup = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Group\n ref={ref}\n className={cn(\n \"text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium\",\n className,\n )}\n {...props}\n />\n));\n\nCommandGroup.displayName = CommandPrimitive.Group.displayName;\n\nconst CommandSeparator = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Separator\n ref={ref}\n className={cn(\"bg-border -mx-1 h-px\", className)}\n {...props}\n />\n));\nCommandSeparator.displayName = CommandPrimitive.Separator.displayName;\n\nconst CommandItem = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Item\n ref={ref}\n className={cn(\n \"aria-selected:bg-accent aria-selected:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n />\n));\n\nCommandItem.displayName = CommandPrimitive.Item.displayName;\n\nconst CommandShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn(\n \"text-muted-foreground ml-auto text-xs tracking-widest\",\n className,\n )}\n {...props}\n />\n );\n};\nCommandShortcut.displayName = \"CommandShortcut\";\n\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandSeparator,\n CommandShortcut,\n};\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@radix-ui/react-dialog",
15
+ "cmdk",
16
+ "lucide-react"
17
+ ],
18
+ "registryDependencies": [
19
+ "dialog"
20
+ ]
21
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "dialog",
4
+ "type": "registry:component",
5
+ "description": "A window overlaid on either the primary window or another dialog window.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/dialog.tsx",
10
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\n\nimport { cn } from \"@aomi-labs/react\";\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n showCloseButton?: boolean;\n}) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-background data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed left-[50%] top-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg\",\n className,\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"rounded-xs ring-offset-background focus:ring-ring focus:outline-hidden data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0\"\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg font-semibold leading-none\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "@radix-ui/react-dialog",
15
+ "lucide-react"
16
+ ],
17
+ "registryDependencies": []
18
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "drawer",
4
+ "type": "registry:component",
5
+ "description": "A drawer component for mobile navigation menus and similar interfaces.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/drawer.tsx",
10
+ "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Drawer as DrawerPrimitive } from \"vaul\";\n\nimport { cn } from \"@aomi-labs/react\";\n\nconst Drawer = ({\n shouldScaleBackground = true,\n ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) => (\n <DrawerPrimitive.Root\n shouldScaleBackground={shouldScaleBackground}\n {...props}\n />\n);\nDrawer.displayName = \"Drawer\";\n\nconst DrawerTrigger = DrawerPrimitive.Trigger;\n\nconst DrawerPortal = DrawerPrimitive.Portal;\n\nconst DrawerClose = DrawerPrimitive.Close;\n\nconst DrawerOverlay = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DrawerPrimitive.Overlay\n ref={ref}\n className={cn(\"fixed inset-0 z-50 bg-black/80\", className)}\n {...props}\n />\n));\nDrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;\n\nconst DrawerContent = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DrawerPortal>\n <DrawerOverlay />\n <DrawerPrimitive.Content\n ref={ref}\n className={cn(\n \"bg-background fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border\",\n className,\n )}\n {...props}\n >\n <div className=\"bg-muted mx-auto mt-4 h-2 w-[100px] rounded-full\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n));\nDrawerContent.displayName = \"DrawerContent\";\n\nconst DrawerHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\"grid gap-1.5 p-4 text-center sm:text-left\", className)}\n {...props}\n />\n);\nDrawerHeader.displayName = \"DrawerHeader\";\n\nconst DrawerFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n);\nDrawerFooter.displayName = \"DrawerFooter\";\n\nconst DrawerTitle = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DrawerPrimitive.Title\n ref={ref}\n className={cn(\n \"text-lg font-semibold leading-none tracking-tight\",\n className,\n )}\n {...props}\n />\n));\nDrawerTitle.displayName = DrawerPrimitive.Title.displayName;\n\nconst DrawerDescription = React.forwardRef<\n React.ElementRef<typeof DrawerPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DrawerPrimitive.Description\n ref={ref}\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n));\nDrawerDescription.displayName = DrawerPrimitive.Description.displayName;\n\nexport {\n Drawer,\n DrawerPortal,\n DrawerOverlay,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n};\n"
11
+ }
12
+ ],
13
+ "dependencies": [
14
+ "vaul"
15
+ ],
16
+ "registryDependencies": []
17
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "input",
4
+ "type": "registry:component",
5
+ "description": "Displays a form input field or a component that looks like an input field.",
6
+ "files": [
7
+ {
8
+ "type": "registry:component",
9
+ "path": "components/ui/input.tsx",
10
+ "content": "import * as React from \"react\";\n\nimport { cn } from \"@aomi-labs/react\";\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"border-sm border-input shadow-xs selection:bg-primary selection:text-primary-foreground file:text-foreground placeholder:text-muted-foreground dark:bg-input/30 flex h-9 w-full min-w-0 rounded-md bg-transparent px-3 py-1 text-base outline-none transition-[color,box-shadow] file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]\",\n \"aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Input };\n"
11
+ }
12
+ ],
13
+ "dependencies": [],
14
+ "registryDependencies": []
15
+ }