@gram-ai/elements 1.18.4 → 1.18.6

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 (87) hide show
  1. package/dist/components/Chat/stories/Sidecar.stories.d.ts +6 -0
  2. package/dist/elements.cjs +23 -22
  3. package/dist/elements.cjs.map +1 -0
  4. package/dist/elements.js +609 -599
  5. package/dist/elements.js.map +1 -0
  6. package/dist/index-Bj7jPiuy.cjs +1 -0
  7. package/dist/index-Bj7jPiuy.cjs.map +1 -0
  8. package/dist/index-CJRypLIa.js +1 -0
  9. package/dist/index-CJRypLIa.js.map +1 -0
  10. package/dist/lib/api.d.ts +2 -0
  11. package/dist/lib/api.test.d.ts +1 -0
  12. package/dist/plugins.cjs +1 -0
  13. package/dist/plugins.cjs.map +1 -0
  14. package/dist/plugins.js +1 -0
  15. package/dist/plugins.js.map +1 -0
  16. package/dist/server.cjs +1 -0
  17. package/dist/server.cjs.map +1 -0
  18. package/dist/server.js +1 -0
  19. package/dist/server.js.map +1 -0
  20. package/package.json +6 -2
  21. package/src/components/Chat/index.tsx +21 -0
  22. package/src/components/Chat/stories/ColorScheme.stories.tsx +52 -0
  23. package/src/components/Chat/stories/Composer.stories.tsx +42 -0
  24. package/src/components/Chat/stories/Customization.stories.tsx +88 -0
  25. package/src/components/Chat/stories/Density.stories.tsx +52 -0
  26. package/src/components/Chat/stories/FrontendTools.stories.tsx +145 -0
  27. package/src/components/Chat/stories/Modal.stories.tsx +84 -0
  28. package/src/components/Chat/stories/Model.stories.tsx +32 -0
  29. package/src/components/Chat/stories/Plugins.stories.tsx +50 -0
  30. package/src/components/Chat/stories/Radius.stories.tsx +52 -0
  31. package/src/components/Chat/stories/Sidecar.stories.tsx +27 -0
  32. package/src/components/Chat/stories/ToolApproval.stories.tsx +110 -0
  33. package/src/components/Chat/stories/Tools.stories.tsx +175 -0
  34. package/src/components/Chat/stories/Variants.stories.tsx +46 -0
  35. package/src/components/Chat/stories/Welcome.stories.tsx +42 -0
  36. package/src/components/FrontendTools/index.tsx +9 -0
  37. package/src/components/assistant-ui/assistant-modal.tsx +255 -0
  38. package/src/components/assistant-ui/assistant-sidecar.tsx +88 -0
  39. package/src/components/assistant-ui/attachment.tsx +233 -0
  40. package/src/components/assistant-ui/markdown-text.tsx +240 -0
  41. package/src/components/assistant-ui/reasoning.tsx +261 -0
  42. package/src/components/assistant-ui/thread-list.tsx +97 -0
  43. package/src/components/assistant-ui/thread.tsx +632 -0
  44. package/src/components/assistant-ui/tool-fallback.tsx +111 -0
  45. package/src/components/assistant-ui/tool-group.tsx +59 -0
  46. package/src/components/assistant-ui/tooltip-icon-button.tsx +57 -0
  47. package/src/components/ui/avatar.tsx +51 -0
  48. package/src/components/ui/button.tsx +27 -0
  49. package/src/components/ui/buttonVariants.ts +33 -0
  50. package/src/components/ui/collapsible.tsx +31 -0
  51. package/src/components/ui/dialog.tsx +141 -0
  52. package/src/components/ui/popover.tsx +46 -0
  53. package/src/components/ui/skeleton.tsx +13 -0
  54. package/src/components/ui/tool-ui.stories.tsx +146 -0
  55. package/src/components/ui/tool-ui.tsx +676 -0
  56. package/src/components/ui/tooltip.tsx +61 -0
  57. package/src/contexts/ElementsProvider.tsx +256 -0
  58. package/src/contexts/ToolApprovalContext.tsx +120 -0
  59. package/src/contexts/contexts.ts +10 -0
  60. package/src/global.css +136 -0
  61. package/src/hooks/useAuth.ts +71 -0
  62. package/src/hooks/useDensity.ts +110 -0
  63. package/src/hooks/useElements.ts +14 -0
  64. package/src/hooks/useExpanded.ts +20 -0
  65. package/src/hooks/useMCPTools.ts +73 -0
  66. package/src/hooks/usePluginComponents.ts +34 -0
  67. package/src/hooks/useRadius.ts +42 -0
  68. package/src/hooks/useSession.ts +38 -0
  69. package/src/hooks/useThemeProps.ts +24 -0
  70. package/src/hooks/useToolApproval.ts +16 -0
  71. package/src/index.ts +45 -0
  72. package/src/lib/api.test.ts +90 -0
  73. package/src/lib/api.ts +8 -0
  74. package/src/lib/auth.ts +10 -0
  75. package/src/lib/easing.ts +1 -0
  76. package/src/lib/humanize.ts +14 -0
  77. package/src/lib/models.ts +22 -0
  78. package/src/lib/tools.ts +210 -0
  79. package/src/lib/utils.ts +16 -0
  80. package/src/plugins/README.md +49 -0
  81. package/src/plugins/chart/component.tsx +102 -0
  82. package/src/plugins/chart/index.ts +27 -0
  83. package/src/plugins/index.ts +7 -0
  84. package/src/server.ts +89 -0
  85. package/src/types/index.ts +726 -0
  86. package/src/types/plugins.ts +65 -0
  87. package/src/vite-env.d.ts +12 -0
@@ -0,0 +1,111 @@
1
+ import { cn } from '@/lib/utils'
2
+ import {
3
+ useAssistantState,
4
+ type ToolCallMessagePartComponent,
5
+ } from '@assistant-ui/react'
6
+ import { useToolApproval } from '@/hooks/useToolApproval'
7
+ import {
8
+ ToolUI,
9
+ type ToolStatus,
10
+ type ContentItem,
11
+ } from '@/components/ui/tool-ui'
12
+
13
+ export const ToolFallback: ToolCallMessagePartComponent = ({
14
+ toolName,
15
+ toolCallId,
16
+ status,
17
+ result,
18
+ args,
19
+ }) => {
20
+ const {
21
+ pendingApprovals,
22
+ whitelistTool,
23
+ confirmPendingApproval,
24
+ rejectPendingApproval,
25
+ } = useToolApproval()
26
+
27
+ // Check if this specific tool call has a pending approval
28
+ const pendingApproval = pendingApprovals.get(toolCallId)
29
+ const message = useAssistantState(({ message }) => message)
30
+ const toolParts = message.parts.filter((part) => part.type === 'tool-call')
31
+ const matchingMessagePartIndex = toolParts.findIndex(
32
+ (part) => part.toolName === toolName
33
+ )
34
+
35
+ const handleApproveOnce = () => {
36
+ confirmPendingApproval(toolCallId)
37
+ }
38
+
39
+ const handleApproveForSession = () => {
40
+ whitelistTool(toolName)
41
+ confirmPendingApproval(toolCallId)
42
+ }
43
+
44
+ const handleDeny = () => {
45
+ rejectPendingApproval(toolCallId)
46
+ }
47
+
48
+ // Map assistant-ui status to ToolUI status
49
+ const getToolStatus = (): ToolStatus => {
50
+ if (pendingApproval) return 'approval'
51
+ if (status.type === 'incomplete') return 'error'
52
+ if (status.type === 'complete') {
53
+ // Check if the result indicates an error (e.g., tool was denied)
54
+ if (
55
+ result &&
56
+ typeof result === 'object' &&
57
+ 'isError' in result &&
58
+ result.isError
59
+ ) {
60
+ return 'error'
61
+ }
62
+ return 'complete'
63
+ }
64
+ return 'running'
65
+ }
66
+
67
+ // Parse result to structured content if possible
68
+ const getResult = ():
69
+ | string
70
+ | Record<string, unknown>
71
+ | { content: ContentItem[] }
72
+ | undefined => {
73
+ if (result === undefined) return undefined
74
+ // Check if it's structured content with a content array
75
+ if (
76
+ typeof result === 'object' &&
77
+ result !== null &&
78
+ 'content' in result &&
79
+ Array.isArray((result as { content: unknown }).content)
80
+ ) {
81
+ return result as { content: ContentItem[] }
82
+ }
83
+ // Otherwise return as-is (string or object)
84
+ if (typeof result === 'string') return result
85
+ return result as Record<string, unknown>
86
+ }
87
+
88
+ return (
89
+ <div
90
+ className={cn(
91
+ 'aui-tool-fallback-root flex w-full flex-col',
92
+ matchingMessagePartIndex !== -1 &&
93
+ matchingMessagePartIndex !== toolParts.length - 1 &&
94
+ 'border-b'
95
+ )}
96
+ >
97
+ <ToolUI
98
+ name={toolName}
99
+ status={getToolStatus()}
100
+ request={args as Record<string, unknown>}
101
+ result={getResult()}
102
+ onApproveOnce={pendingApproval ? handleApproveOnce : undefined}
103
+ onApproveForSession={
104
+ pendingApproval ? handleApproveForSession : undefined
105
+ }
106
+ onDeny={pendingApproval ? handleDeny : undefined}
107
+ className="rounded-none border-0"
108
+ />
109
+ </div>
110
+ )
111
+ }
@@ -0,0 +1,59 @@
1
+ import { cn } from '@/lib/utils'
2
+ import { useAssistantState } from '@assistant-ui/react'
3
+ import { useMemo, type FC, type PropsWithChildren } from 'react'
4
+ import { useElements } from '@/hooks/useElements'
5
+ import { humanizeToolName } from '@/lib/humanize'
6
+ import { ToolUIGroup } from '@/components/ui/tool-ui'
7
+
8
+ export const ToolGroup: FC<
9
+ PropsWithChildren<{ startIndex: number; endIndex: number }>
10
+ > = ({ children }) => {
11
+ const parts = useAssistantState(({ message }) => message).parts
12
+ const toolCallParts = parts.filter((part) => part.type === 'tool-call')
13
+ const anyMessagePartsAreRunning = toolCallParts.some(
14
+ (part) => part.status?.type === 'running'
15
+ )
16
+
17
+ const { config } = useElements()
18
+ const defaultExpanded = config.tools?.expandToolGroupsByDefault ?? false
19
+
20
+ const groupTitle = useMemo(() => {
21
+ const toolParts = parts.filter((part) => part.type === 'tool-call')
22
+
23
+ if (toolParts.length === 0) return 'No tools called'
24
+ if (toolParts.length === 1)
25
+ return `Calling ${humanizeToolName(toolParts[0].toolName)}...`
26
+ return anyMessagePartsAreRunning
27
+ ? `Calling ${toolParts.length} tools...`
28
+ : `Executed ${toolParts.length} tools`
29
+ }, [parts, anyMessagePartsAreRunning])
30
+
31
+ // If there's a custom component for the single tool, render children directly
32
+ if (config.tools?.components?.[toolCallParts[0]?.toolName]) {
33
+ return children
34
+ }
35
+
36
+ // For single tool calls, render without the group wrapper
37
+ if (toolCallParts.length === 1) {
38
+ return (
39
+ <div className={cn('my-4 w-full max-w-xl')}>
40
+ <div className="border-border bg-card overflow-hidden rounded-lg border">
41
+ {children}
42
+ </div>
43
+ </div>
44
+ )
45
+ }
46
+
47
+ // For multiple tool calls, use the group component
48
+ return (
49
+ <div className="my-4 w-full max-w-xl">
50
+ <ToolUIGroup
51
+ title={groupTitle}
52
+ status={anyMessagePartsAreRunning ? 'running' : 'complete'}
53
+ defaultExpanded={defaultExpanded}
54
+ >
55
+ {children}
56
+ </ToolUIGroup>
57
+ </div>
58
+ )
59
+ }
@@ -0,0 +1,57 @@
1
+ 'use client'
2
+
3
+ import { ComponentPropsWithRef, forwardRef } from 'react'
4
+ import { Slottable } from '@radix-ui/react-slot'
5
+
6
+ import {
7
+ Tooltip,
8
+ TooltipContent,
9
+ TooltipTrigger,
10
+ } from '@/components/ui/tooltip'
11
+ import { Button } from '@/components/ui/button'
12
+ import { cn } from '@/lib/utils'
13
+
14
+ type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
15
+ tooltip: string
16
+ side?: 'top' | 'bottom' | 'left' | 'right'
17
+ align?: 'start' | 'center' | 'end'
18
+ }
19
+
20
+ export const TooltipIconButton = forwardRef<
21
+ HTMLButtonElement,
22
+ TooltipIconButtonProps
23
+ >(
24
+ (
25
+ {
26
+ children,
27
+ tooltip,
28
+ side = 'bottom',
29
+ align = 'center',
30
+ className,
31
+ ...rest
32
+ },
33
+ ref
34
+ ) => {
35
+ return (
36
+ <Tooltip>
37
+ <TooltipTrigger asChild>
38
+ <Button
39
+ variant="ghost"
40
+ size="icon"
41
+ {...rest}
42
+ className={cn('aui-button-icon size-6 p-1', className)}
43
+ ref={ref}
44
+ >
45
+ <Slottable>{children}</Slottable>
46
+ <span className="aui-sr-only sr-only">{tooltip}</span>
47
+ </Button>
48
+ </TooltipTrigger>
49
+ <TooltipContent side={side} align={align}>
50
+ {tooltip}
51
+ </TooltipContent>
52
+ </Tooltip>
53
+ )
54
+ }
55
+ )
56
+
57
+ TooltipIconButton.displayName = 'TooltipIconButton'
@@ -0,0 +1,51 @@
1
+ import * as React from 'react'
2
+ import * as AvatarPrimitive from '@radix-ui/react-avatar'
3
+
4
+ import { cn } from '@/lib/utils'
5
+
6
+ function Avatar({
7
+ className,
8
+ ...props
9
+ }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
10
+ return (
11
+ <AvatarPrimitive.Root
12
+ data-slot="avatar"
13
+ className={cn(
14
+ 'relative flex size-8 shrink-0 overflow-hidden rounded-full',
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ function AvatarImage({
23
+ className,
24
+ ...props
25
+ }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
26
+ return (
27
+ <AvatarPrimitive.Image
28
+ data-slot="avatar-image"
29
+ className={cn('aspect-square size-full', className)}
30
+ {...props}
31
+ />
32
+ )
33
+ }
34
+
35
+ function AvatarFallback({
36
+ className,
37
+ ...props
38
+ }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
39
+ return (
40
+ <AvatarPrimitive.Fallback
41
+ data-slot="avatar-fallback"
42
+ className={cn(
43
+ 'bg-muted flex size-full items-center justify-center rounded-full',
44
+ className
45
+ )}
46
+ {...props}
47
+ />
48
+ )
49
+ }
50
+
51
+ export { Avatar, AvatarImage, AvatarFallback }
@@ -0,0 +1,27 @@
1
+ import * as React from 'react'
2
+ import { Slot } from '@radix-ui/react-slot'
3
+ import { type VariantProps } from 'class-variance-authority'
4
+
5
+ import { cn } from '@/lib/utils'
6
+ import { buttonVariants } from './buttonVariants'
7
+
8
+ const Button = React.forwardRef<
9
+ HTMLButtonElement,
10
+ React.ComponentProps<'button'> &
11
+ VariantProps<typeof buttonVariants> & {
12
+ asChild?: boolean
13
+ }
14
+ >(({ className, variant, size, asChild = false, ...props }, ref) => {
15
+ const Comp = asChild ? Slot : 'button'
16
+ return (
17
+ <Comp
18
+ data-slot="button"
19
+ className={cn(buttonVariants({ variant, size, className }))}
20
+ ref={ref}
21
+ {...props}
22
+ />
23
+ )
24
+ })
25
+ Button.displayName = 'Button'
26
+
27
+ export { Button }
@@ -0,0 +1,33 @@
1
+ import { cva } from 'class-variance-authority'
2
+
3
+ export const buttonVariants = cva(
4
+ "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",
5
+ {
6
+ variants: {
7
+ variant: {
8
+ default: 'bg-primary text-primary-foreground hover:bg-primary/90',
9
+ destructive:
10
+ 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
11
+ outline:
12
+ 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
13
+ secondary:
14
+ 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
15
+ ghost:
16
+ 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
17
+ link: 'text-primary underline-offset-4 hover:underline',
18
+ },
19
+ size: {
20
+ default: 'h-9 px-4 py-2 has-[>svg]:px-3',
21
+ sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
22
+ lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
23
+ icon: 'size-9',
24
+ 'icon-sm': 'size-8',
25
+ 'icon-lg': 'size-10',
26
+ },
27
+ },
28
+ defaultVariants: {
29
+ variant: 'default',
30
+ size: 'default',
31
+ },
32
+ }
33
+ )
@@ -0,0 +1,31 @@
1
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'
2
+
3
+ function Collapsible({
4
+ ...props
5
+ }: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
6
+ return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
7
+ }
8
+
9
+ function CollapsibleTrigger({
10
+ ...props
11
+ }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
12
+ return (
13
+ <CollapsiblePrimitive.CollapsibleTrigger
14
+ data-slot="collapsible-trigger"
15
+ {...props}
16
+ />
17
+ )
18
+ }
19
+
20
+ function CollapsibleContent({
21
+ ...props
22
+ }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
23
+ return (
24
+ <CollapsiblePrimitive.CollapsibleContent
25
+ data-slot="collapsible-content"
26
+ {...props}
27
+ />
28
+ )
29
+ }
30
+
31
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent }
@@ -0,0 +1,141 @@
1
+ import * as React from 'react'
2
+ import * as DialogPrimitive from '@radix-ui/react-dialog'
3
+ import { XIcon } from 'lucide-react'
4
+
5
+ import { cn } from '@/lib/utils'
6
+
7
+ function Dialog({
8
+ ...props
9
+ }: React.ComponentProps<typeof DialogPrimitive.Root>) {
10
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />
11
+ }
12
+
13
+ function DialogTrigger({
14
+ ...props
15
+ }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
16
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
17
+ }
18
+
19
+ function DialogPortal({
20
+ ...props
21
+ }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
22
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
23
+ }
24
+
25
+ function DialogClose({
26
+ ...props
27
+ }: React.ComponentProps<typeof DialogPrimitive.Close>) {
28
+ return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
29
+ }
30
+
31
+ function DialogOverlay({
32
+ className,
33
+ ...props
34
+ }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
35
+ return (
36
+ <DialogPrimitive.Overlay
37
+ data-slot="dialog-overlay"
38
+ className={cn(
39
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
40
+ className
41
+ )}
42
+ {...props}
43
+ />
44
+ )
45
+ }
46
+
47
+ function DialogContent({
48
+ className,
49
+ children,
50
+ showCloseButton = true,
51
+ ...props
52
+ }: React.ComponentProps<typeof DialogPrimitive.Content> & {
53
+ showCloseButton?: boolean
54
+ }) {
55
+ return (
56
+ <DialogPortal data-slot="dialog-portal">
57
+ <DialogOverlay />
58
+ <DialogPrimitive.Content
59
+ data-slot="dialog-content"
60
+ className={cn(
61
+ 'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[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',
62
+ className
63
+ )}
64
+ {...props}
65
+ >
66
+ {children}
67
+ {showCloseButton && (
68
+ <DialogPrimitive.Close
69
+ data-slot="dialog-close"
70
+ className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
71
+ >
72
+ <XIcon />
73
+ <span className="sr-only">Close</span>
74
+ </DialogPrimitive.Close>
75
+ )}
76
+ </DialogPrimitive.Content>
77
+ </DialogPortal>
78
+ )
79
+ }
80
+
81
+ function DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {
82
+ return (
83
+ <div
84
+ data-slot="dialog-header"
85
+ className={cn('flex flex-col gap-2 text-center sm:text-left', className)}
86
+ {...props}
87
+ />
88
+ )
89
+ }
90
+
91
+ function DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {
92
+ return (
93
+ <div
94
+ data-slot="dialog-footer"
95
+ className={cn(
96
+ 'flex flex-col-reverse gap-2 sm:flex-row sm:justify-end',
97
+ className
98
+ )}
99
+ {...props}
100
+ />
101
+ )
102
+ }
103
+
104
+ function DialogTitle({
105
+ className,
106
+ ...props
107
+ }: React.ComponentProps<typeof DialogPrimitive.Title>) {
108
+ return (
109
+ <DialogPrimitive.Title
110
+ data-slot="dialog-title"
111
+ className={cn('text-lg leading-none font-semibold', className)}
112
+ {...props}
113
+ />
114
+ )
115
+ }
116
+
117
+ function DialogDescription({
118
+ className,
119
+ ...props
120
+ }: React.ComponentProps<typeof DialogPrimitive.Description>) {
121
+ return (
122
+ <DialogPrimitive.Description
123
+ data-slot="dialog-description"
124
+ className={cn('text-muted-foreground text-sm', className)}
125
+ {...props}
126
+ />
127
+ )
128
+ }
129
+
130
+ export {
131
+ Dialog,
132
+ DialogClose,
133
+ DialogContent,
134
+ DialogDescription,
135
+ DialogFooter,
136
+ DialogHeader,
137
+ DialogOverlay,
138
+ DialogPortal,
139
+ DialogTitle,
140
+ DialogTrigger,
141
+ }
@@ -0,0 +1,46 @@
1
+ import * as React from 'react'
2
+ import * as PopoverPrimitive from '@radix-ui/react-popover'
3
+
4
+ import { cn } from '@/lib/utils'
5
+
6
+ function Popover({
7
+ ...props
8
+ }: React.ComponentProps<typeof PopoverPrimitive.Root>) {
9
+ return <PopoverPrimitive.Root data-slot="popover" {...props} />
10
+ }
11
+
12
+ function PopoverTrigger({
13
+ ...props
14
+ }: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
15
+ return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
16
+ }
17
+
18
+ function PopoverContent({
19
+ className,
20
+ align = 'center',
21
+ sideOffset = 4,
22
+ ...props
23
+ }: React.ComponentProps<typeof PopoverPrimitive.Content>) {
24
+ return (
25
+ <PopoverPrimitive.Portal>
26
+ <PopoverPrimitive.Content
27
+ data-slot="popover-content"
28
+ align={align}
29
+ sideOffset={sideOffset}
30
+ className={cn(
31
+ 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-20 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden',
32
+ className
33
+ )}
34
+ {...props}
35
+ />
36
+ </PopoverPrimitive.Portal>
37
+ )
38
+ }
39
+
40
+ function PopoverAnchor({
41
+ ...props
42
+ }: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
43
+ return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
44
+ }
45
+
46
+ export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
@@ -0,0 +1,13 @@
1
+ import { cn } from '@/lib/utils'
2
+
3
+ function Skeleton({ className, ...props }: React.ComponentProps<'div'>) {
4
+ return (
5
+ <div
6
+ data-slot="skeleton"
7
+ className={cn('bg-accent animate-pulse rounded-md', className)}
8
+ {...props}
9
+ />
10
+ )
11
+ }
12
+
13
+ export { Skeleton }