@gram-ai/elements 1.25.2 → 1.26.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.
- package/dist/components/Chat/stories/Charts.stories.d.ts +37 -0
- package/dist/components/Chat/stories/GenerativeUI.stories.d.ts +17 -0
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/buttonVariants.d.ts +1 -1
- package/dist/components/ui/charts.stories.d.ts +43 -0
- package/dist/components/ui/generative-ui.stories.d.ts +53 -0
- package/dist/components/ui/tool-ui.d.ts +16 -1
- package/dist/elements.cjs +1 -1
- package/dist/elements.css +1 -1
- package/dist/elements.js +6 -6
- package/dist/index-BpJstUh1.cjs +280 -0
- package/dist/index-BpJstUh1.cjs.map +1 -0
- package/dist/index-CUitXazZ.js +30426 -0
- package/dist/index-CUitXazZ.js.map +1 -0
- package/dist/index-DdrZQXwQ.cjs +147 -0
- package/dist/index-DdrZQXwQ.cjs.map +1 -0
- package/dist/index-DfqYP0CD.js +37062 -0
- package/dist/index-DfqYP0CD.js.map +1 -0
- package/dist/plugins/chart/catalog.d.ts +123 -0
- package/dist/plugins/chart/index.d.ts +1 -1
- package/dist/plugins/chart/ui/area-chart.d.ts +16 -0
- package/dist/plugins/chart/ui/bar-chart.d.ts +16 -0
- package/dist/plugins/chart/ui/donut-chart.d.ts +17 -0
- package/dist/plugins/chart/ui/index.d.ts +7 -0
- package/dist/plugins/chart/ui/line-chart.d.ts +17 -0
- package/dist/plugins/chart/ui/pie-chart.d.ts +15 -0
- package/dist/plugins/chart/ui/radar-chart.d.ts +14 -0
- package/dist/plugins/chart/ui/scatter-chart.d.ts +18 -0
- package/dist/plugins/components/MacOSWindowFrame.d.ts +13 -0
- package/dist/plugins/components/PluginLoadingState.d.ts +1 -1
- package/dist/plugins/generative-ui/catalog.d.ts +293 -0
- package/dist/plugins/generative-ui/ui/accordion-wrapper.d.ts +18 -0
- package/dist/plugins/generative-ui/ui/accordion.d.ts +7 -0
- package/dist/plugins/generative-ui/ui/action-button.d.ts +10 -0
- package/dist/plugins/generative-ui/ui/alert-wrapper.d.ts +9 -0
- package/dist/plugins/generative-ui/ui/alert.d.ts +9 -0
- package/dist/plugins/generative-ui/ui/avatar-wrapper.d.ts +9 -0
- package/dist/plugins/generative-ui/ui/avatar.d.ts +11 -0
- package/dist/plugins/generative-ui/ui/badge.d.ts +12 -0
- package/dist/plugins/generative-ui/ui/button-wrapper.d.ts +15 -0
- package/dist/plugins/generative-ui/ui/button.d.ts +10 -0
- package/dist/plugins/generative-ui/ui/card-wrapper.d.ts +10 -0
- package/dist/plugins/generative-ui/ui/card.d.ts +9 -0
- package/dist/plugins/generative-ui/ui/checkbox-wrapper.d.ts +10 -0
- package/dist/plugins/generative-ui/ui/checkbox.d.ts +4 -0
- package/dist/plugins/generative-ui/ui/data-table.d.ts +10 -0
- package/dist/plugins/generative-ui/ui/dialog.d.ts +17 -0
- package/dist/plugins/generative-ui/ui/dropdown-menu.d.ts +25 -0
- package/dist/plugins/generative-ui/ui/grid.d.ts +6 -0
- package/dist/plugins/generative-ui/ui/index.d.ts +40 -0
- package/dist/plugins/generative-ui/ui/input-wrapper.d.ts +11 -0
- package/dist/plugins/generative-ui/ui/input.d.ts +3 -0
- package/dist/plugins/generative-ui/ui/label.d.ts +4 -0
- package/dist/plugins/generative-ui/ui/list.d.ts +6 -0
- package/dist/plugins/generative-ui/ui/metric.d.ts +7 -0
- package/dist/plugins/generative-ui/ui/pagination.d.ts +13 -0
- package/dist/plugins/generative-ui/ui/popover.d.ts +10 -0
- package/dist/plugins/generative-ui/ui/progress.d.ts +10 -0
- package/dist/plugins/generative-ui/ui/radio-group.d.ts +5 -0
- package/dist/plugins/generative-ui/ui/select-wrapper.d.ts +13 -0
- package/dist/plugins/generative-ui/ui/select.d.ts +15 -0
- package/dist/plugins/generative-ui/ui/separator.d.ts +4 -0
- package/dist/plugins/generative-ui/ui/skeleton-wrapper.d.ts +9 -0
- package/dist/plugins/generative-ui/ui/skeleton.d.ts +2 -0
- package/dist/plugins/generative-ui/ui/stack.d.ts +8 -0
- package/dist/plugins/generative-ui/ui/switch.d.ts +6 -0
- package/dist/plugins/generative-ui/ui/table.d.ts +10 -0
- package/dist/plugins/generative-ui/ui/tabs-wrapper.d.ts +21 -0
- package/dist/plugins/generative-ui/ui/tabs.d.ts +11 -0
- package/dist/plugins/generative-ui/ui/text.d.ts +7 -0
- package/dist/plugins/generative-ui/ui/textarea.d.ts +3 -0
- package/dist/plugins/generative-ui/ui/tooltip.d.ts +7 -0
- package/dist/plugins.cjs +1 -1
- package/dist/plugins.js +1 -1
- package/dist/{profiler-BaG0scxd.js → profiler-WoFj2UH8.js} +2 -2
- package/dist/{profiler-BaG0scxd.js.map → profiler-WoFj2UH8.js.map} +1 -1
- package/dist/{profiler-CuqENACf.cjs → profiler-ZLr2-8s7.cjs} +2 -2
- package/dist/{profiler-CuqENACf.cjs.map → profiler-ZLr2-8s7.cjs.map} +1 -1
- package/dist/{startRecording-BiLmoqZa.cjs → startRecording-BGnWDInp.cjs} +2 -2
- package/dist/{startRecording-BiLmoqZa.cjs.map → startRecording-BGnWDInp.cjs.map} +1 -1
- package/dist/{startRecording-86bHmd-l.js → startRecording-DzQo16WK.js} +2 -2
- package/dist/{startRecording-86bHmd-l.js.map → startRecording-DzQo16WK.js.map} +1 -1
- package/package.json +4 -1
- package/src/components/Chat/stories/Charts.stories.tsx +260 -0
- package/src/components/Chat/stories/ConnectionConfiguration.stories.tsx +6 -6
- package/src/components/Chat/stories/GenerativeUI.stories.tsx +113 -0
- package/src/components/Replay.stories.tsx +1 -1
- package/src/components/Replay.tsx +18 -13
- package/src/components/ui/charts.stories.tsx +246 -0
- package/src/components/ui/generative-ui.stories.tsx +557 -0
- package/src/components/ui/generative-ui.tsx +60 -360
- package/src/components/ui/tool-ui.stories.tsx +6 -3
- package/src/components/ui/tool-ui.tsx +31 -2
- package/src/hooks/useAuth.ts +17 -1
- package/src/hooks/useFollowOnSuggestions.ts +6 -1
- package/src/plugins/chart/catalog.ts +141 -0
- package/src/plugins/chart/component.tsx +79 -125
- package/src/plugins/chart/index.ts +141 -89
- package/src/plugins/chart/ui/area-chart.tsx +133 -0
- package/src/plugins/chart/ui/bar-chart.tsx +137 -0
- package/src/plugins/chart/ui/donut-chart.tsx +167 -0
- package/src/plugins/chart/ui/index.ts +7 -0
- package/src/plugins/chart/ui/line-chart.tsx +135 -0
- package/src/plugins/chart/ui/pie-chart.tsx +148 -0
- package/src/plugins/chart/ui/radar-chart.tsx +105 -0
- package/src/plugins/chart/ui/scatter-chart.tsx +132 -0
- package/src/plugins/components/MacOSWindowFrame.tsx +55 -0
- package/src/plugins/components/PluginLoadingState.tsx +9 -13
- package/src/plugins/generative-ui/catalog.ts +277 -0
- package/src/plugins/generative-ui/component.tsx +112 -21
- package/src/plugins/generative-ui/index.ts +20 -141
- package/src/plugins/generative-ui/ui/accordion-wrapper.tsx +57 -0
- package/src/plugins/generative-ui/ui/accordion.tsx +66 -0
- package/src/plugins/generative-ui/ui/action-button.tsx +68 -0
- package/src/plugins/generative-ui/ui/alert-wrapper.tsx +26 -0
- package/src/plugins/generative-ui/ui/alert.tsx +66 -0
- package/src/plugins/generative-ui/ui/avatar-wrapper.tsx +22 -0
- package/src/plugins/generative-ui/ui/avatar.tsx +109 -0
- package/src/plugins/generative-ui/ui/badge.tsx +65 -0
- package/src/plugins/generative-ui/ui/button-wrapper.tsx +32 -0
- package/src/plugins/generative-ui/ui/button.tsx +65 -0
- package/src/plugins/generative-ui/ui/card-wrapper.tsx +36 -0
- package/src/plugins/generative-ui/ui/card.tsx +92 -0
- package/src/plugins/generative-ui/ui/checkbox-wrapper.tsx +39 -0
- package/src/plugins/generative-ui/ui/checkbox.tsx +32 -0
- package/src/plugins/generative-ui/ui/data-table.tsx +53 -0
- package/src/plugins/generative-ui/ui/dialog.tsx +158 -0
- package/src/plugins/generative-ui/ui/dropdown-menu.tsx +257 -0
- package/src/plugins/generative-ui/ui/grid.tsx +29 -0
- package/src/plugins/generative-ui/ui/index.ts +43 -0
- package/src/plugins/generative-ui/ui/input-wrapper.tsx +38 -0
- package/src/plugins/generative-ui/ui/input.tsx +21 -0
- package/src/plugins/generative-ui/ui/label.tsx +24 -0
- package/src/plugins/generative-ui/ui/list.tsx +34 -0
- package/src/plugins/generative-ui/ui/metric.tsx +53 -0
- package/src/plugins/generative-ui/ui/pagination.tsx +127 -0
- package/src/plugins/generative-ui/ui/popover.tsx +89 -0
- package/src/plugins/generative-ui/ui/progress.tsx +57 -0
- package/src/plugins/generative-ui/ui/radio-group.tsx +45 -0
- package/src/plugins/generative-ui/ui/select-wrapper.tsx +41 -0
- package/src/plugins/generative-ui/ui/select.tsx +190 -0
- package/src/plugins/generative-ui/ui/separator.tsx +28 -0
- package/src/plugins/generative-ui/ui/skeleton-wrapper.tsx +30 -0
- package/src/plugins/generative-ui/ui/skeleton.tsx +13 -0
- package/src/plugins/generative-ui/ui/stack.tsx +54 -0
- package/src/plugins/generative-ui/ui/switch.tsx +35 -0
- package/src/plugins/generative-ui/ui/table.tsx +116 -0
- package/src/plugins/generative-ui/ui/tabs-wrapper.tsx +51 -0
- package/src/plugins/generative-ui/ui/tabs.tsx +92 -0
- package/src/plugins/generative-ui/ui/text.tsx +33 -0
- package/src/plugins/generative-ui/ui/textarea.tsx +18 -0
- package/src/plugins/generative-ui/ui/tooltip.tsx +57 -0
- package/dist/components/Chat/stories/Plugins.stories.d.ts +0 -12
- package/dist/index-B8nSCdu4.cjs +0 -251
- package/dist/index-B8nSCdu4.cjs.map +0 -1
- package/dist/index-CAtaLV1E.cjs +0 -187
- package/dist/index-CAtaLV1E.cjs.map +0 -1
- package/dist/index-CJrwma08.js +0 -27232
- package/dist/index-CJrwma08.js.map +0 -1
- package/dist/index-DLWQ91ow.js +0 -40049
- package/dist/index-DLWQ91ow.js.map +0 -1
- package/src/components/Chat/stories/Plugins.stories.tsx +0 -158
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { ChevronDownIcon } from 'lucide-react'
|
|
5
|
+
import { Accordion as AccordionPrimitive } from 'radix-ui'
|
|
6
|
+
|
|
7
|
+
import { cn } from '@/lib/utils'
|
|
8
|
+
|
|
9
|
+
function Accordion({
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
|
12
|
+
return <AccordionPrimitive.Root data-slot="accordion" {...props} />
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function AccordionItem({
|
|
16
|
+
className,
|
|
17
|
+
...props
|
|
18
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
|
|
19
|
+
return (
|
|
20
|
+
<AccordionPrimitive.Item
|
|
21
|
+
data-slot="accordion-item"
|
|
22
|
+
className={cn('border-b last:border-b-0', className)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function AccordionTrigger({
|
|
29
|
+
className,
|
|
30
|
+
children,
|
|
31
|
+
...props
|
|
32
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
|
|
33
|
+
return (
|
|
34
|
+
<AccordionPrimitive.Header className="flex">
|
|
35
|
+
<AccordionPrimitive.Trigger
|
|
36
|
+
data-slot="accordion-trigger"
|
|
37
|
+
className={cn(
|
|
38
|
+
'text-foreground focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180',
|
|
39
|
+
className
|
|
40
|
+
)}
|
|
41
|
+
{...props}
|
|
42
|
+
>
|
|
43
|
+
{children}
|
|
44
|
+
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
|
|
45
|
+
</AccordionPrimitive.Trigger>
|
|
46
|
+
</AccordionPrimitive.Header>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function AccordionContent({
|
|
51
|
+
className,
|
|
52
|
+
children,
|
|
53
|
+
...props
|
|
54
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
|
|
55
|
+
return (
|
|
56
|
+
<AccordionPrimitive.Content
|
|
57
|
+
data-slot="accordion-content"
|
|
58
|
+
className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
|
|
59
|
+
{...props}
|
|
60
|
+
>
|
|
61
|
+
<div className={cn('pt-0 pb-4', className)}>{children}</div>
|
|
62
|
+
</AccordionPrimitive.Content>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Button, buttonVariants } from './button'
|
|
5
|
+
import type { VariantProps } from 'class-variance-authority'
|
|
6
|
+
import { cn } from '@/lib/utils'
|
|
7
|
+
import { useToolExecution } from '@/contexts/ToolExecutionContext'
|
|
8
|
+
|
|
9
|
+
export interface ActionButtonProps
|
|
10
|
+
extends
|
|
11
|
+
Omit<React.ComponentProps<'button'>, 'onClick'>,
|
|
12
|
+
VariantProps<typeof buttonVariants> {
|
|
13
|
+
label: string
|
|
14
|
+
/** Tool name to invoke when clicked (matches LLM prompt) */
|
|
15
|
+
action: string
|
|
16
|
+
args?: Record<string, unknown>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function ActionButton({
|
|
20
|
+
label,
|
|
21
|
+
action,
|
|
22
|
+
args,
|
|
23
|
+
variant = 'default',
|
|
24
|
+
size = 'default',
|
|
25
|
+
className,
|
|
26
|
+
disabled,
|
|
27
|
+
...props
|
|
28
|
+
}: ActionButtonProps) {
|
|
29
|
+
const { executeTool, isToolAvailable } = useToolExecution()
|
|
30
|
+
const [isLoading, setIsLoading] = React.useState(false)
|
|
31
|
+
|
|
32
|
+
const toolAvailable = isToolAvailable(action)
|
|
33
|
+
|
|
34
|
+
const [error, setError] = React.useState<string | null>(null)
|
|
35
|
+
|
|
36
|
+
const handleClick = React.useCallback(async () => {
|
|
37
|
+
if (!toolAvailable || isLoading) return
|
|
38
|
+
|
|
39
|
+
setIsLoading(true)
|
|
40
|
+
setError(null)
|
|
41
|
+
try {
|
|
42
|
+
const result = await executeTool(action, args ?? {})
|
|
43
|
+
if (!result.success && result.error) {
|
|
44
|
+
setError(result.error)
|
|
45
|
+
}
|
|
46
|
+
} catch (err) {
|
|
47
|
+
setError(err instanceof Error ? err.message : 'Unknown error')
|
|
48
|
+
} finally {
|
|
49
|
+
setIsLoading(false)
|
|
50
|
+
}
|
|
51
|
+
}, [action, args, executeTool, isLoading, toolAvailable])
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<div className="inline-flex flex-col gap-1">
|
|
55
|
+
<Button
|
|
56
|
+
variant={error ? 'destructive' : variant}
|
|
57
|
+
size={size}
|
|
58
|
+
className={cn(className)}
|
|
59
|
+
onClick={handleClick}
|
|
60
|
+
disabled={disabled || isLoading || !toolAvailable}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
{isLoading ? 'Loading...' : label}
|
|
64
|
+
</Button>
|
|
65
|
+
{error && <span className="text-destructive text-xs">{error}</span>}
|
|
66
|
+
</div>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Alert, AlertTitle, AlertDescription } from './alert'
|
|
5
|
+
|
|
6
|
+
export interface AlertWrapperProps {
|
|
7
|
+
title: string
|
|
8
|
+
description?: string
|
|
9
|
+
variant?: 'default' | 'destructive'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Alert wrapper that takes title and description as props.
|
|
14
|
+
*/
|
|
15
|
+
export function AlertWrapper({
|
|
16
|
+
title,
|
|
17
|
+
description,
|
|
18
|
+
variant = 'default',
|
|
19
|
+
}: AlertWrapperProps) {
|
|
20
|
+
return (
|
|
21
|
+
<Alert variant={variant}>
|
|
22
|
+
<AlertTitle>{title}</AlertTitle>
|
|
23
|
+
{description && <AlertDescription>{description}</AlertDescription>}
|
|
24
|
+
</Alert>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority'
|
|
3
|
+
|
|
4
|
+
import { cn } from '@/lib/utils'
|
|
5
|
+
|
|
6
|
+
const alertVariants = cva(
|
|
7
|
+
'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current',
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: 'bg-card text-card-foreground',
|
|
12
|
+
destructive:
|
|
13
|
+
'text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
variant: 'default',
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
function Alert({
|
|
23
|
+
className,
|
|
24
|
+
variant,
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>) {
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
data-slot="alert"
|
|
30
|
+
role="alert"
|
|
31
|
+
className={cn(alertVariants({ variant }), className)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
data-slot="alert-title"
|
|
41
|
+
className={cn(
|
|
42
|
+
'col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight',
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function AlertDescription({
|
|
51
|
+
className,
|
|
52
|
+
...props
|
|
53
|
+
}: React.ComponentProps<'div'>) {
|
|
54
|
+
return (
|
|
55
|
+
<div
|
|
56
|
+
data-slot="alert-description"
|
|
57
|
+
className={cn(
|
|
58
|
+
'text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed',
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { Alert, AlertTitle, AlertDescription }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Avatar, AvatarImage, AvatarFallback } from './avatar'
|
|
5
|
+
|
|
6
|
+
export interface AvatarWrapperProps {
|
|
7
|
+
src?: string
|
|
8
|
+
alt?: string
|
|
9
|
+
fallback: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Avatar wrapper that takes src, alt, and fallback as props.
|
|
14
|
+
*/
|
|
15
|
+
export function AvatarWrapper({ src, alt, fallback }: AvatarWrapperProps) {
|
|
16
|
+
return (
|
|
17
|
+
<Avatar>
|
|
18
|
+
{src && <AvatarImage src={src} alt={alt} />}
|
|
19
|
+
<AvatarFallback>{fallback}</AvatarFallback>
|
|
20
|
+
</Avatar>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Avatar as AvatarPrimitive } from 'radix-ui'
|
|
5
|
+
|
|
6
|
+
import { cn } from '@/lib/utils'
|
|
7
|
+
|
|
8
|
+
function Avatar({
|
|
9
|
+
className,
|
|
10
|
+
size = 'default',
|
|
11
|
+
...props
|
|
12
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Root> & {
|
|
13
|
+
size?: 'default' | 'sm' | 'lg'
|
|
14
|
+
}) {
|
|
15
|
+
return (
|
|
16
|
+
<AvatarPrimitive.Root
|
|
17
|
+
data-slot="avatar"
|
|
18
|
+
data-size={size}
|
|
19
|
+
className={cn(
|
|
20
|
+
'group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6',
|
|
21
|
+
className
|
|
22
|
+
)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function AvatarImage({
|
|
29
|
+
className,
|
|
30
|
+
...props
|
|
31
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
|
|
32
|
+
return (
|
|
33
|
+
<AvatarPrimitive.Image
|
|
34
|
+
data-slot="avatar-image"
|
|
35
|
+
className={cn('aspect-square size-full', className)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function AvatarFallback({
|
|
42
|
+
className,
|
|
43
|
+
...props
|
|
44
|
+
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
|
|
45
|
+
return (
|
|
46
|
+
<AvatarPrimitive.Fallback
|
|
47
|
+
data-slot="avatar-fallback"
|
|
48
|
+
className={cn(
|
|
49
|
+
'bg-muted text-muted-foreground flex size-full items-center justify-center rounded-full text-sm group-data-[size=sm]/avatar:text-xs',
|
|
50
|
+
className
|
|
51
|
+
)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function AvatarBadge({ className, ...props }: React.ComponentProps<'span'>) {
|
|
58
|
+
return (
|
|
59
|
+
<span
|
|
60
|
+
data-slot="avatar-badge"
|
|
61
|
+
className={cn(
|
|
62
|
+
'bg-primary text-primary-foreground ring-background absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full ring-2 select-none',
|
|
63
|
+
'group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden',
|
|
64
|
+
'group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2',
|
|
65
|
+
'group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2',
|
|
66
|
+
className
|
|
67
|
+
)}
|
|
68
|
+
{...props}
|
|
69
|
+
/>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function AvatarGroup({ className, ...props }: React.ComponentProps<'div'>) {
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
data-slot="avatar-group"
|
|
77
|
+
className={cn(
|
|
78
|
+
'*:data-[slot=avatar]:ring-background group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2',
|
|
79
|
+
className
|
|
80
|
+
)}
|
|
81
|
+
{...props}
|
|
82
|
+
/>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function AvatarGroupCount({
|
|
87
|
+
className,
|
|
88
|
+
...props
|
|
89
|
+
}: React.ComponentProps<'div'>) {
|
|
90
|
+
return (
|
|
91
|
+
<div
|
|
92
|
+
data-slot="avatar-group-count"
|
|
93
|
+
className={cn(
|
|
94
|
+
'bg-muted text-muted-foreground ring-background relative flex size-8 shrink-0 items-center justify-center rounded-full text-sm ring-2 group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3',
|
|
95
|
+
className
|
|
96
|
+
)}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
Avatar,
|
|
104
|
+
AvatarImage,
|
|
105
|
+
AvatarFallback,
|
|
106
|
+
AvatarBadge,
|
|
107
|
+
AvatarGroup,
|
|
108
|
+
AvatarGroupCount,
|
|
109
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority'
|
|
3
|
+
import { Slot } from 'radix-ui'
|
|
4
|
+
|
|
5
|
+
import { cn } from '@/lib/utils'
|
|
6
|
+
|
|
7
|
+
const badgeVariants = cva(
|
|
8
|
+
'inline-flex items-center justify-center rounded-full border border-transparent px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-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 transition-[color,box-shadow] overflow-hidden',
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: 'bg-primary text-primary-foreground [a&]:hover:bg-primary/90',
|
|
13
|
+
secondary:
|
|
14
|
+
'bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',
|
|
15
|
+
/** Matches LLM prompt variant */
|
|
16
|
+
success:
|
|
17
|
+
'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-100',
|
|
18
|
+
/** Matches LLM prompt variant */
|
|
19
|
+
warning:
|
|
20
|
+
'bg-amber-100 text-amber-800 dark:bg-amber-900 dark:text-amber-100',
|
|
21
|
+
/** Matches LLM prompt variant */
|
|
22
|
+
error: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-100',
|
|
23
|
+
destructive:
|
|
24
|
+
'bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
|
25
|
+
outline:
|
|
26
|
+
'border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: {
|
|
30
|
+
variant: 'default',
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
interface BadgeProps
|
|
36
|
+
extends React.ComponentProps<'span'>, VariantProps<typeof badgeVariants> {
|
|
37
|
+
asChild?: boolean
|
|
38
|
+
/** Content text (matches LLM prompt) - rendered as children */
|
|
39
|
+
content?: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function Badge({
|
|
43
|
+
className,
|
|
44
|
+
variant = 'default',
|
|
45
|
+
asChild = false,
|
|
46
|
+
content,
|
|
47
|
+
children,
|
|
48
|
+
...props
|
|
49
|
+
}: BadgeProps) {
|
|
50
|
+
const Comp = asChild ? Slot.Root : 'span'
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Comp
|
|
54
|
+
data-slot="badge"
|
|
55
|
+
data-variant={variant}
|
|
56
|
+
className={cn(badgeVariants({ variant }), className)}
|
|
57
|
+
{...props}
|
|
58
|
+
>
|
|
59
|
+
{content ?? children}
|
|
60
|
+
</Comp>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
65
|
+
export { Badge, badgeVariants }
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Button } from './button'
|
|
5
|
+
|
|
6
|
+
export interface ButtonWrapperProps {
|
|
7
|
+
label: string
|
|
8
|
+
variant?: 'default' | 'secondary' | 'destructive' | 'outline' | 'ghost'
|
|
9
|
+
size?: 'default' | 'sm' | 'lg' | 'icon'
|
|
10
|
+
disabled?: boolean
|
|
11
|
+
/** Backend action to trigger (future use) */
|
|
12
|
+
action?: string
|
|
13
|
+
/** Parameters for the action (future use) */
|
|
14
|
+
actionParams?: Record<string, unknown>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Button wrapper that takes label as a prop.
|
|
19
|
+
* The action/actionParams props are for future backend integration.
|
|
20
|
+
*/
|
|
21
|
+
export function ButtonWrapper({
|
|
22
|
+
label,
|
|
23
|
+
variant = 'default',
|
|
24
|
+
size = 'default',
|
|
25
|
+
disabled = false,
|
|
26
|
+
}: ButtonWrapperProps) {
|
|
27
|
+
return (
|
|
28
|
+
<Button variant={variant} size={size} disabled={disabled}>
|
|
29
|
+
{label}
|
|
30
|
+
</Button>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority'
|
|
3
|
+
import { Slot } from 'radix-ui'
|
|
4
|
+
|
|
5
|
+
import { cn } from '@/lib/utils'
|
|
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: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
13
|
+
destructive:
|
|
14
|
+
'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
|
15
|
+
outline:
|
|
16
|
+
'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
|
|
17
|
+
secondary:
|
|
18
|
+
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
19
|
+
ghost:
|
|
20
|
+
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
|
|
21
|
+
link: 'text-primary underline-offset-4 hover:underline',
|
|
22
|
+
},
|
|
23
|
+
size: {
|
|
24
|
+
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
|
|
25
|
+
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-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
|
+
'icon-xs': "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
30
|
+
'icon-sm': 'size-8',
|
|
31
|
+
'icon-lg': 'size-10',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
variant: 'default',
|
|
36
|
+
size: 'default',
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
function Button({
|
|
42
|
+
className,
|
|
43
|
+
variant = 'default',
|
|
44
|
+
size = 'default',
|
|
45
|
+
asChild = false,
|
|
46
|
+
...props
|
|
47
|
+
}: React.ComponentProps<'button'> &
|
|
48
|
+
VariantProps<typeof buttonVariants> & {
|
|
49
|
+
asChild?: boolean
|
|
50
|
+
}) {
|
|
51
|
+
const Comp = asChild ? Slot.Root : 'button'
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Comp
|
|
55
|
+
data-slot="button"
|
|
56
|
+
data-variant={variant}
|
|
57
|
+
data-size={size}
|
|
58
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
65
|
+
export { Button, buttonVariants }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { cn } from '@/lib/utils'
|
|
3
|
+
|
|
4
|
+
export interface CardWrapperProps extends React.ComponentProps<'div'> {
|
|
5
|
+
title?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* CardWrapper is a frameless container for generative UI content.
|
|
10
|
+
* It has no border or shadow since it's rendered inside MacOSWindowFrame.
|
|
11
|
+
* Children are spaced using flex gap for proper composition.
|
|
12
|
+
*/
|
|
13
|
+
export function CardWrapper({
|
|
14
|
+
title,
|
|
15
|
+
className,
|
|
16
|
+
children,
|
|
17
|
+
...props
|
|
18
|
+
}: CardWrapperProps) {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
data-slot="card-wrapper"
|
|
22
|
+
className={cn(
|
|
23
|
+
'bg-card text-card-foreground flex flex-col gap-6 p-6',
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
{...props}
|
|
27
|
+
>
|
|
28
|
+
{title && (
|
|
29
|
+
<div className="text-foreground text-lg leading-none font-semibold">
|
|
30
|
+
{title}
|
|
31
|
+
</div>
|
|
32
|
+
)}
|
|
33
|
+
<div className="flex flex-col gap-6">{children}</div>
|
|
34
|
+
</div>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
import { cn } from '@/lib/utils'
|
|
4
|
+
|
|
5
|
+
function Card({ className, ...props }: React.ComponentProps<'div'>) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="card"
|
|
9
|
+
className={cn(
|
|
10
|
+
'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm',
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
data-slot="card-header"
|
|
22
|
+
className={cn(
|
|
23
|
+
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
|
32
|
+
return (
|
|
33
|
+
<div
|
|
34
|
+
data-slot="card-title"
|
|
35
|
+
className={cn('leading-none font-semibold', className)}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
data-slot="card-description"
|
|
45
|
+
className={cn('text-muted-foreground text-sm', className)}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
|
|
52
|
+
return (
|
|
53
|
+
<div
|
|
54
|
+
data-slot="card-action"
|
|
55
|
+
className={cn(
|
|
56
|
+
'col-start-2 row-span-2 row-start-1 self-start justify-self-end',
|
|
57
|
+
className
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
|
|
65
|
+
return (
|
|
66
|
+
<div
|
|
67
|
+
data-slot="card-content"
|
|
68
|
+
className={cn('px-6', className)}
|
|
69
|
+
{...props}
|
|
70
|
+
/>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
75
|
+
return (
|
|
76
|
+
<div
|
|
77
|
+
data-slot="card-footer"
|
|
78
|
+
className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
Card,
|
|
86
|
+
CardHeader,
|
|
87
|
+
CardFooter,
|
|
88
|
+
CardTitle,
|
|
89
|
+
CardAction,
|
|
90
|
+
CardDescription,
|
|
91
|
+
CardContent,
|
|
92
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Checkbox } from './checkbox'
|
|
5
|
+
import { Label } from './label'
|
|
6
|
+
|
|
7
|
+
export interface CheckboxWrapperProps {
|
|
8
|
+
label?: string
|
|
9
|
+
/** Path for form state management (future use) */
|
|
10
|
+
valuePath: string
|
|
11
|
+
defaultChecked?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Checkbox wrapper that adds label support.
|
|
16
|
+
*/
|
|
17
|
+
export function CheckboxWrapper({
|
|
18
|
+
label,
|
|
19
|
+
valuePath,
|
|
20
|
+
defaultChecked,
|
|
21
|
+
}: CheckboxWrapperProps) {
|
|
22
|
+
const id = React.useId()
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className="flex items-center gap-2">
|
|
26
|
+
<Checkbox
|
|
27
|
+
id={id}
|
|
28
|
+
name={valuePath}
|
|
29
|
+
defaultChecked={defaultChecked}
|
|
30
|
+
data-value-path={valuePath}
|
|
31
|
+
/>
|
|
32
|
+
{label && (
|
|
33
|
+
<Label htmlFor={id} className="cursor-pointer">
|
|
34
|
+
{label}
|
|
35
|
+
</Label>
|
|
36
|
+
)}
|
|
37
|
+
</div>
|
|
38
|
+
)
|
|
39
|
+
}
|