@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.
Files changed (162) hide show
  1. package/dist/components/Chat/stories/Charts.stories.d.ts +37 -0
  2. package/dist/components/Chat/stories/GenerativeUI.stories.d.ts +17 -0
  3. package/dist/components/ui/button.d.ts +1 -1
  4. package/dist/components/ui/buttonVariants.d.ts +1 -1
  5. package/dist/components/ui/charts.stories.d.ts +43 -0
  6. package/dist/components/ui/generative-ui.stories.d.ts +53 -0
  7. package/dist/components/ui/tool-ui.d.ts +16 -1
  8. package/dist/elements.cjs +1 -1
  9. package/dist/elements.css +1 -1
  10. package/dist/elements.js +6 -6
  11. package/dist/index-BpJstUh1.cjs +280 -0
  12. package/dist/index-BpJstUh1.cjs.map +1 -0
  13. package/dist/index-CUitXazZ.js +30426 -0
  14. package/dist/index-CUitXazZ.js.map +1 -0
  15. package/dist/index-DdrZQXwQ.cjs +147 -0
  16. package/dist/index-DdrZQXwQ.cjs.map +1 -0
  17. package/dist/index-DfqYP0CD.js +37062 -0
  18. package/dist/index-DfqYP0CD.js.map +1 -0
  19. package/dist/plugins/chart/catalog.d.ts +123 -0
  20. package/dist/plugins/chart/index.d.ts +1 -1
  21. package/dist/plugins/chart/ui/area-chart.d.ts +16 -0
  22. package/dist/plugins/chart/ui/bar-chart.d.ts +16 -0
  23. package/dist/plugins/chart/ui/donut-chart.d.ts +17 -0
  24. package/dist/plugins/chart/ui/index.d.ts +7 -0
  25. package/dist/plugins/chart/ui/line-chart.d.ts +17 -0
  26. package/dist/plugins/chart/ui/pie-chart.d.ts +15 -0
  27. package/dist/plugins/chart/ui/radar-chart.d.ts +14 -0
  28. package/dist/plugins/chart/ui/scatter-chart.d.ts +18 -0
  29. package/dist/plugins/components/MacOSWindowFrame.d.ts +13 -0
  30. package/dist/plugins/components/PluginLoadingState.d.ts +1 -1
  31. package/dist/plugins/generative-ui/catalog.d.ts +293 -0
  32. package/dist/plugins/generative-ui/ui/accordion-wrapper.d.ts +18 -0
  33. package/dist/plugins/generative-ui/ui/accordion.d.ts +7 -0
  34. package/dist/plugins/generative-ui/ui/action-button.d.ts +10 -0
  35. package/dist/plugins/generative-ui/ui/alert-wrapper.d.ts +9 -0
  36. package/dist/plugins/generative-ui/ui/alert.d.ts +9 -0
  37. package/dist/plugins/generative-ui/ui/avatar-wrapper.d.ts +9 -0
  38. package/dist/plugins/generative-ui/ui/avatar.d.ts +11 -0
  39. package/dist/plugins/generative-ui/ui/badge.d.ts +12 -0
  40. package/dist/plugins/generative-ui/ui/button-wrapper.d.ts +15 -0
  41. package/dist/plugins/generative-ui/ui/button.d.ts +10 -0
  42. package/dist/plugins/generative-ui/ui/card-wrapper.d.ts +10 -0
  43. package/dist/plugins/generative-ui/ui/card.d.ts +9 -0
  44. package/dist/plugins/generative-ui/ui/checkbox-wrapper.d.ts +10 -0
  45. package/dist/plugins/generative-ui/ui/checkbox.d.ts +4 -0
  46. package/dist/plugins/generative-ui/ui/data-table.d.ts +10 -0
  47. package/dist/plugins/generative-ui/ui/dialog.d.ts +17 -0
  48. package/dist/plugins/generative-ui/ui/dropdown-menu.d.ts +25 -0
  49. package/dist/plugins/generative-ui/ui/grid.d.ts +6 -0
  50. package/dist/plugins/generative-ui/ui/index.d.ts +40 -0
  51. package/dist/plugins/generative-ui/ui/input-wrapper.d.ts +11 -0
  52. package/dist/plugins/generative-ui/ui/input.d.ts +3 -0
  53. package/dist/plugins/generative-ui/ui/label.d.ts +4 -0
  54. package/dist/plugins/generative-ui/ui/list.d.ts +6 -0
  55. package/dist/plugins/generative-ui/ui/metric.d.ts +7 -0
  56. package/dist/plugins/generative-ui/ui/pagination.d.ts +13 -0
  57. package/dist/plugins/generative-ui/ui/popover.d.ts +10 -0
  58. package/dist/plugins/generative-ui/ui/progress.d.ts +10 -0
  59. package/dist/plugins/generative-ui/ui/radio-group.d.ts +5 -0
  60. package/dist/plugins/generative-ui/ui/select-wrapper.d.ts +13 -0
  61. package/dist/plugins/generative-ui/ui/select.d.ts +15 -0
  62. package/dist/plugins/generative-ui/ui/separator.d.ts +4 -0
  63. package/dist/plugins/generative-ui/ui/skeleton-wrapper.d.ts +9 -0
  64. package/dist/plugins/generative-ui/ui/skeleton.d.ts +2 -0
  65. package/dist/plugins/generative-ui/ui/stack.d.ts +8 -0
  66. package/dist/plugins/generative-ui/ui/switch.d.ts +6 -0
  67. package/dist/plugins/generative-ui/ui/table.d.ts +10 -0
  68. package/dist/plugins/generative-ui/ui/tabs-wrapper.d.ts +21 -0
  69. package/dist/plugins/generative-ui/ui/tabs.d.ts +11 -0
  70. package/dist/plugins/generative-ui/ui/text.d.ts +7 -0
  71. package/dist/plugins/generative-ui/ui/textarea.d.ts +3 -0
  72. package/dist/plugins/generative-ui/ui/tooltip.d.ts +7 -0
  73. package/dist/plugins.cjs +1 -1
  74. package/dist/plugins.js +1 -1
  75. package/dist/{profiler-BaG0scxd.js → profiler-WoFj2UH8.js} +2 -2
  76. package/dist/{profiler-BaG0scxd.js.map → profiler-WoFj2UH8.js.map} +1 -1
  77. package/dist/{profiler-CuqENACf.cjs → profiler-ZLr2-8s7.cjs} +2 -2
  78. package/dist/{profiler-CuqENACf.cjs.map → profiler-ZLr2-8s7.cjs.map} +1 -1
  79. package/dist/{startRecording-BiLmoqZa.cjs → startRecording-BGnWDInp.cjs} +2 -2
  80. package/dist/{startRecording-BiLmoqZa.cjs.map → startRecording-BGnWDInp.cjs.map} +1 -1
  81. package/dist/{startRecording-86bHmd-l.js → startRecording-DzQo16WK.js} +2 -2
  82. package/dist/{startRecording-86bHmd-l.js.map → startRecording-DzQo16WK.js.map} +1 -1
  83. package/package.json +4 -1
  84. package/src/components/Chat/stories/Charts.stories.tsx +260 -0
  85. package/src/components/Chat/stories/ConnectionConfiguration.stories.tsx +6 -6
  86. package/src/components/Chat/stories/GenerativeUI.stories.tsx +113 -0
  87. package/src/components/Replay.stories.tsx +1 -1
  88. package/src/components/Replay.tsx +18 -13
  89. package/src/components/ui/charts.stories.tsx +246 -0
  90. package/src/components/ui/generative-ui.stories.tsx +557 -0
  91. package/src/components/ui/generative-ui.tsx +60 -360
  92. package/src/components/ui/tool-ui.stories.tsx +6 -3
  93. package/src/components/ui/tool-ui.tsx +31 -2
  94. package/src/hooks/useAuth.ts +17 -1
  95. package/src/hooks/useFollowOnSuggestions.ts +6 -1
  96. package/src/plugins/chart/catalog.ts +141 -0
  97. package/src/plugins/chart/component.tsx +79 -125
  98. package/src/plugins/chart/index.ts +141 -89
  99. package/src/plugins/chart/ui/area-chart.tsx +133 -0
  100. package/src/plugins/chart/ui/bar-chart.tsx +137 -0
  101. package/src/plugins/chart/ui/donut-chart.tsx +167 -0
  102. package/src/plugins/chart/ui/index.ts +7 -0
  103. package/src/plugins/chart/ui/line-chart.tsx +135 -0
  104. package/src/plugins/chart/ui/pie-chart.tsx +148 -0
  105. package/src/plugins/chart/ui/radar-chart.tsx +105 -0
  106. package/src/plugins/chart/ui/scatter-chart.tsx +132 -0
  107. package/src/plugins/components/MacOSWindowFrame.tsx +55 -0
  108. package/src/plugins/components/PluginLoadingState.tsx +9 -13
  109. package/src/plugins/generative-ui/catalog.ts +277 -0
  110. package/src/plugins/generative-ui/component.tsx +112 -21
  111. package/src/plugins/generative-ui/index.ts +20 -141
  112. package/src/plugins/generative-ui/ui/accordion-wrapper.tsx +57 -0
  113. package/src/plugins/generative-ui/ui/accordion.tsx +66 -0
  114. package/src/plugins/generative-ui/ui/action-button.tsx +68 -0
  115. package/src/plugins/generative-ui/ui/alert-wrapper.tsx +26 -0
  116. package/src/plugins/generative-ui/ui/alert.tsx +66 -0
  117. package/src/plugins/generative-ui/ui/avatar-wrapper.tsx +22 -0
  118. package/src/plugins/generative-ui/ui/avatar.tsx +109 -0
  119. package/src/plugins/generative-ui/ui/badge.tsx +65 -0
  120. package/src/plugins/generative-ui/ui/button-wrapper.tsx +32 -0
  121. package/src/plugins/generative-ui/ui/button.tsx +65 -0
  122. package/src/plugins/generative-ui/ui/card-wrapper.tsx +36 -0
  123. package/src/plugins/generative-ui/ui/card.tsx +92 -0
  124. package/src/plugins/generative-ui/ui/checkbox-wrapper.tsx +39 -0
  125. package/src/plugins/generative-ui/ui/checkbox.tsx +32 -0
  126. package/src/plugins/generative-ui/ui/data-table.tsx +53 -0
  127. package/src/plugins/generative-ui/ui/dialog.tsx +158 -0
  128. package/src/plugins/generative-ui/ui/dropdown-menu.tsx +257 -0
  129. package/src/plugins/generative-ui/ui/grid.tsx +29 -0
  130. package/src/plugins/generative-ui/ui/index.ts +43 -0
  131. package/src/plugins/generative-ui/ui/input-wrapper.tsx +38 -0
  132. package/src/plugins/generative-ui/ui/input.tsx +21 -0
  133. package/src/plugins/generative-ui/ui/label.tsx +24 -0
  134. package/src/plugins/generative-ui/ui/list.tsx +34 -0
  135. package/src/plugins/generative-ui/ui/metric.tsx +53 -0
  136. package/src/plugins/generative-ui/ui/pagination.tsx +127 -0
  137. package/src/plugins/generative-ui/ui/popover.tsx +89 -0
  138. package/src/plugins/generative-ui/ui/progress.tsx +57 -0
  139. package/src/plugins/generative-ui/ui/radio-group.tsx +45 -0
  140. package/src/plugins/generative-ui/ui/select-wrapper.tsx +41 -0
  141. package/src/plugins/generative-ui/ui/select.tsx +190 -0
  142. package/src/plugins/generative-ui/ui/separator.tsx +28 -0
  143. package/src/plugins/generative-ui/ui/skeleton-wrapper.tsx +30 -0
  144. package/src/plugins/generative-ui/ui/skeleton.tsx +13 -0
  145. package/src/plugins/generative-ui/ui/stack.tsx +54 -0
  146. package/src/plugins/generative-ui/ui/switch.tsx +35 -0
  147. package/src/plugins/generative-ui/ui/table.tsx +116 -0
  148. package/src/plugins/generative-ui/ui/tabs-wrapper.tsx +51 -0
  149. package/src/plugins/generative-ui/ui/tabs.tsx +92 -0
  150. package/src/plugins/generative-ui/ui/text.tsx +33 -0
  151. package/src/plugins/generative-ui/ui/textarea.tsx +18 -0
  152. package/src/plugins/generative-ui/ui/tooltip.tsx +57 -0
  153. package/dist/components/Chat/stories/Plugins.stories.d.ts +0 -12
  154. package/dist/index-B8nSCdu4.cjs +0 -251
  155. package/dist/index-B8nSCdu4.cjs.map +0 -1
  156. package/dist/index-CAtaLV1E.cjs +0 -187
  157. package/dist/index-CAtaLV1E.cjs.map +0 -1
  158. package/dist/index-CJrwma08.js +0 -27232
  159. package/dist/index-CJrwma08.js.map +0 -1
  160. package/dist/index-DLWQ91ow.js +0 -40049
  161. package/dist/index-DLWQ91ow.js.map +0 -1
  162. package/src/components/Chat/stories/Plugins.stories.tsx +0 -158
@@ -0,0 +1,148 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@/lib/utils'
4
+ import { FC } from 'react'
5
+ import {
6
+ PieChart as RechartsPieChart,
7
+ Pie,
8
+ Cell,
9
+ Tooltip,
10
+ Legend,
11
+ ResponsiveContainer,
12
+ TooltipProps,
13
+ } from 'recharts'
14
+
15
+ const CustomTooltip = ({ active, payload }: TooltipProps<number, string>) => {
16
+ if (!active || !payload || payload.length === 0) return null
17
+ const entry = payload[0]
18
+ return (
19
+ <div className="bg-background text-foreground border-border rounded-md border px-2 py-1 text-xs shadow-sm">
20
+ <span className="font-medium">
21
+ {typeof entry?.value === 'number'
22
+ ? entry.value.toLocaleString()
23
+ : entry?.value}
24
+ </span>
25
+ </div>
26
+ )
27
+ }
28
+
29
+ const COLORS = [
30
+ 'var(--chart-1)',
31
+ 'var(--chart-2)',
32
+ 'var(--chart-3)',
33
+ 'var(--chart-4)',
34
+ 'var(--chart-5)',
35
+ ]
36
+
37
+ interface DataPoint {
38
+ label: string
39
+ value: number
40
+ color?: string
41
+ }
42
+
43
+ export interface PieChartProps {
44
+ title?: string
45
+ data: DataPoint[]
46
+ showLabels?: boolean
47
+ showLegend?: boolean
48
+ className?: string
49
+ }
50
+
51
+ export const PieChart: FC<PieChartProps> = ({
52
+ title,
53
+ data,
54
+ showLabels = true,
55
+ showLegend = true,
56
+ className,
57
+ }) => {
58
+ // Transform data to use 'name' for Recharts
59
+ const chartData = data.map((d) => ({
60
+ name: d.label,
61
+ value: d.value,
62
+ color: d.color,
63
+ }))
64
+
65
+ return (
66
+ <div className={cn('flex flex-col gap-2', className)}>
67
+ {title && (
68
+ <h3 className="text-foreground text-sm font-medium">{title}</h3>
69
+ )}
70
+ <div className="h-[320px] w-full">
71
+ <ResponsiveContainer width="100%" height="100%">
72
+ <RechartsPieChart
73
+ margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
74
+ >
75
+ <Pie
76
+ data={chartData}
77
+ cx="50%"
78
+ cy="45%"
79
+ innerRadius={0}
80
+ outerRadius={80}
81
+ paddingAngle={2}
82
+ dataKey="value"
83
+ label={
84
+ showLabels
85
+ ? ({
86
+ name,
87
+ percent,
88
+ cx,
89
+ cy,
90
+ midAngle,
91
+ outerRadius,
92
+ }: {
93
+ name?: string
94
+ percent?: number
95
+ cx?: number
96
+ cy?: number
97
+ midAngle?: number
98
+ outerRadius?: number
99
+ }) => {
100
+ const RADIAN = Math.PI / 180
101
+ const radius = (outerRadius ?? 80) + 25
102
+ const x =
103
+ (cx ?? 0) +
104
+ radius * Math.cos(-((midAngle ?? 0) * RADIAN))
105
+ const y =
106
+ (cy ?? 0) +
107
+ radius * Math.sin(-((midAngle ?? 0) * RADIAN))
108
+ return (
109
+ <text
110
+ x={x}
111
+ y={y}
112
+ fill="var(--foreground)"
113
+ textAnchor={x > (cx ?? 0) ? 'start' : 'end'}
114
+ dominantBaseline="central"
115
+ fontSize={12}
116
+ >
117
+ {`${name ?? ''} (${((percent ?? 0) * 100).toFixed(0)}%)`}
118
+ </text>
119
+ )
120
+ }
121
+ : undefined
122
+ }
123
+ labelLine={showLabels}
124
+ isAnimationActive={false}
125
+ >
126
+ {chartData.map((entry, index) => (
127
+ <Cell
128
+ key={`cell-${index}`}
129
+ fill={entry.color || COLORS[index % COLORS.length]}
130
+ />
131
+ ))}
132
+ </Pie>
133
+ <Tooltip content={<CustomTooltip />} />
134
+ {showLegend && (
135
+ <Legend
136
+ verticalAlign="bottom"
137
+ wrapperStyle={{ color: 'var(--foreground)', paddingTop: 20 }}
138
+ formatter={(value) => (
139
+ <span style={{ color: 'var(--foreground)' }}>{value}</span>
140
+ )}
141
+ />
142
+ )}
143
+ </RechartsPieChart>
144
+ </ResponsiveContainer>
145
+ </div>
146
+ </div>
147
+ )
148
+ }
@@ -0,0 +1,105 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@/lib/utils'
4
+ import { FC } from 'react'
5
+ import {
6
+ RadarChart as RechartsRadarChart,
7
+ Radar,
8
+ PolarGrid,
9
+ PolarAngleAxis,
10
+ PolarRadiusAxis,
11
+ Tooltip,
12
+ Legend,
13
+ ResponsiveContainer,
14
+ TooltipProps,
15
+ } from 'recharts'
16
+
17
+ const CustomTooltip = ({ active, payload }: TooltipProps<number, string>) => {
18
+ if (!active || !payload || payload.length === 0) return null
19
+ const entry = payload[0]
20
+ return (
21
+ <div className="bg-background text-foreground border-border rounded-md border px-2 py-1 text-xs shadow-sm">
22
+ <span className="font-medium">
23
+ {typeof entry?.value === 'number'
24
+ ? entry.value.toLocaleString()
25
+ : entry?.value}
26
+ </span>
27
+ </div>
28
+ )
29
+ }
30
+
31
+ const COLORS = [
32
+ 'var(--chart-1)',
33
+ 'var(--chart-2)',
34
+ 'var(--chart-3)',
35
+ 'var(--chart-4)',
36
+ 'var(--chart-5)',
37
+ ]
38
+
39
+ interface DataPoint {
40
+ label: string
41
+ value: number
42
+ color?: string
43
+ }
44
+
45
+ export interface RadarChartProps {
46
+ title?: string
47
+ data: DataPoint[]
48
+ showLegend?: boolean
49
+ className?: string
50
+ }
51
+
52
+ export const RadarChart: FC<RadarChartProps> = ({
53
+ title,
54
+ data,
55
+ showLegend = false,
56
+ className,
57
+ }) => {
58
+ // Transform data for Recharts (uses 'subject' for labels)
59
+ const chartData = data.map((d) => ({ subject: d.label, value: d.value }))
60
+
61
+ return (
62
+ <div className={cn('flex flex-col gap-2', className)}>
63
+ {title && (
64
+ <h3 className="text-foreground text-sm font-medium">{title}</h3>
65
+ )}
66
+ <div className="h-[250px] w-full">
67
+ <ResponsiveContainer width="100%" height="100%">
68
+ <RechartsRadarChart
69
+ data={chartData}
70
+ cx="50%"
71
+ cy="50%"
72
+ outerRadius="80%"
73
+ >
74
+ <PolarGrid stroke="var(--border)" />
75
+ <PolarAngleAxis
76
+ dataKey="subject"
77
+ tick={{ fill: 'var(--foreground)', fontSize: 12 }}
78
+ />
79
+ <PolarRadiusAxis
80
+ tick={{ fill: 'var(--foreground)', fontSize: 10 }}
81
+ axisLine={{ stroke: 'var(--border)' }}
82
+ />
83
+ <Tooltip content={<CustomTooltip />} />
84
+ {showLegend && (
85
+ <Legend
86
+ wrapperStyle={{ color: 'var(--foreground)' }}
87
+ formatter={(value) => (
88
+ <span style={{ color: 'var(--foreground)' }}>{value}</span>
89
+ )}
90
+ />
91
+ )}
92
+ <Radar
93
+ name="Value"
94
+ dataKey="value"
95
+ stroke={COLORS[0]}
96
+ fill={COLORS[0]}
97
+ fillOpacity={0.3}
98
+ isAnimationActive={false}
99
+ />
100
+ </RechartsRadarChart>
101
+ </ResponsiveContainer>
102
+ </div>
103
+ </div>
104
+ )
105
+ }
@@ -0,0 +1,132 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@/lib/utils'
4
+ import { FC } from 'react'
5
+ import {
6
+ ScatterChart as RechartsScatterChart,
7
+ Scatter,
8
+ XAxis,
9
+ YAxis,
10
+ CartesianGrid,
11
+ Tooltip,
12
+ ResponsiveContainer,
13
+ ZAxis,
14
+ Cell,
15
+ TooltipProps,
16
+ } from 'recharts'
17
+
18
+ interface ScatterDataPoint {
19
+ x: number
20
+ y: number
21
+ label?: string
22
+ size?: number
23
+ color?: string
24
+ }
25
+
26
+ const CustomTooltip = ({ active, payload }: TooltipProps<number, string>) => {
27
+ if (!active || !payload || payload.length === 0) return null
28
+ const point = payload[0]?.payload as ScatterDataPoint | undefined
29
+ return (
30
+ <div className="bg-background text-foreground border-border rounded-md border px-2 py-1.5 text-xs shadow-sm">
31
+ {point?.label && <div className="font-medium">{point.label}</div>}
32
+ <div>x: {point?.x?.toLocaleString()}</div>
33
+ <div>y: {point?.y?.toLocaleString()}</div>
34
+ </div>
35
+ )
36
+ }
37
+
38
+ const COLORS = [
39
+ 'var(--chart-1)',
40
+ 'var(--chart-2)',
41
+ 'var(--chart-3)',
42
+ 'var(--chart-4)',
43
+ 'var(--chart-5)',
44
+ ]
45
+
46
+ export interface ScatterChartProps {
47
+ title?: string
48
+ data: ScatterDataPoint[]
49
+ xLabel?: string
50
+ yLabel?: string
51
+ showGrid?: boolean
52
+ className?: string
53
+ }
54
+
55
+ export const ScatterChart: FC<ScatterChartProps> = ({
56
+ title,
57
+ data,
58
+ xLabel,
59
+ yLabel,
60
+ showGrid = true,
61
+ className,
62
+ }) => {
63
+ // Check if we have size data for bubble chart effect
64
+ const hasSizeData = data.some((d) => d.size !== undefined)
65
+
66
+ return (
67
+ <div className={cn('flex flex-col gap-2', className)}>
68
+ {title && (
69
+ <h3 className="text-foreground text-sm font-medium">{title}</h3>
70
+ )}
71
+ <div className="h-[250px] w-full">
72
+ <ResponsiveContainer width="100%" height="100%">
73
+ <RechartsScatterChart
74
+ margin={{ top: 10, right: 10, left: 10, bottom: 10 }}
75
+ >
76
+ {showGrid && (
77
+ <CartesianGrid
78
+ strokeDasharray="3 3"
79
+ className="stroke-muted/30"
80
+ />
81
+ )}
82
+ <XAxis
83
+ type="number"
84
+ dataKey="x"
85
+ name={xLabel || 'x'}
86
+ tick={{ fill: 'var(--foreground)', fontSize: 12 }}
87
+ axisLine={{ stroke: 'var(--border)' }}
88
+ tickLine={{ stroke: 'var(--border)' }}
89
+ label={
90
+ xLabel
91
+ ? {
92
+ value: xLabel,
93
+ position: 'bottom',
94
+ offset: -5,
95
+ fill: 'var(--foreground)',
96
+ }
97
+ : undefined
98
+ }
99
+ />
100
+ <YAxis
101
+ type="number"
102
+ dataKey="y"
103
+ name={yLabel || 'y'}
104
+ tick={{ fill: 'var(--foreground)', fontSize: 12 }}
105
+ axisLine={{ stroke: 'var(--border)' }}
106
+ tickLine={{ stroke: 'var(--border)' }}
107
+ label={
108
+ yLabel
109
+ ? {
110
+ value: yLabel,
111
+ angle: -90,
112
+ position: 'left',
113
+ fill: 'var(--foreground)',
114
+ }
115
+ : undefined
116
+ }
117
+ />
118
+ {hasSizeData && (
119
+ <ZAxis type="number" dataKey="size" range={[50, 400]} />
120
+ )}
121
+ <Tooltip content={<CustomTooltip />} />
122
+ <Scatter data={data} fill={COLORS[0]} isAnimationActive={false}>
123
+ {data.map((entry, index) => (
124
+ <Cell key={`cell-${index}`} fill={entry.color || COLORS[0]} />
125
+ ))}
126
+ </Scatter>
127
+ </RechartsScatterChart>
128
+ </ResponsiveContainer>
129
+ </div>
130
+ </div>
131
+ )
132
+ }
@@ -0,0 +1,55 @@
1
+ 'use client'
2
+
3
+ import { useRadius } from '@/hooks/useRadius'
4
+ import { cn } from '@/lib/utils'
5
+ import { FC, ReactNode } from 'react'
6
+
7
+ interface MacOSWindowFrameProps {
8
+ children: ReactNode
9
+ className?: string
10
+ /** Optional title to display in the title bar */
11
+ title?: string
12
+ }
13
+
14
+ /**
15
+ * A macOS-style window frame with traffic light buttons.
16
+ * Wraps content in a bordered container with a title bar.
17
+ */
18
+ export const MacOSWindowFrame: FC<MacOSWindowFrameProps> = ({
19
+ children,
20
+ className,
21
+ title,
22
+ }) => {
23
+ const r = useRadius()
24
+
25
+ return (
26
+ <div className="@container my-4 w-full first:mt-0">
27
+ <div
28
+ className={cn(
29
+ // after:hidden prevents assistant-ui from showing its default code block loading indicator
30
+ 'border-border w-full overflow-hidden border after:hidden @sm:max-w-md @md:max-w-lg @lg:max-w-xl @xl:max-w-2xl',
31
+ r('lg'),
32
+ className
33
+ )}
34
+ >
35
+ {/* Title bar */}
36
+ <div className="border-border bg-muted/50 flex h-8 items-center gap-2 border-b px-3">
37
+ {/* Traffic lights */}
38
+ <div className="flex items-center gap-1.5">
39
+ <div className="size-3 rounded-full bg-[#FF5F57]" />
40
+ <div className="size-3 rounded-full bg-[#FEBC2E]" />
41
+ <div className="size-3 rounded-full bg-[#28C840]" />
42
+ </div>
43
+ {/* Title */}
44
+ {title && (
45
+ <span className="text-muted-foreground flex-1 text-center text-xs font-medium">
46
+ {title}
47
+ </span>
48
+ )}
49
+ </div>
50
+ {/* Content */}
51
+ {children}
52
+ </div>
53
+ </div>
54
+ )
55
+ }
@@ -1,8 +1,8 @@
1
1
  'use client'
2
2
 
3
- import { useRadius } from '@/hooks/useRadius'
4
3
  import { cn } from '@/lib/utils'
5
4
  import { FC } from 'react'
5
+ import { MacOSWindowFrame } from './MacOSWindowFrame'
6
6
 
7
7
  interface PluginLoadingStateProps {
8
8
  text: string
@@ -11,25 +11,21 @@ interface PluginLoadingStateProps {
11
11
 
12
12
  /**
13
13
  * Shared loading state component for plugins.
14
- * Displays a shimmer effect with loading text.
14
+ * Displays a shimmer effect with loading text inside a macOS-style window.
15
15
  */
16
16
  export const PluginLoadingState: FC<PluginLoadingStateProps> = ({
17
17
  text,
18
18
  className,
19
19
  }) => {
20
- const r = useRadius()
21
-
22
20
  return (
23
- <div
24
- className={cn(
25
- 'border-border bg-card relative min-h-[400px] w-fit max-w-full min-w-[400px] overflow-hidden border after:hidden',
26
- r('lg'),
27
- className
28
- )}
29
- >
30
- <div className="bg-muted absolute inset-0 flex items-center justify-center">
21
+ <MacOSWindowFrame className={className}>
22
+ <div
23
+ className={cn(
24
+ 'bg-background relative flex min-h-[400px] items-center justify-center'
25
+ )}
26
+ >
31
27
  <span className="shimmer text-muted-foreground text-sm">{text}</span>
32
28
  </div>
33
- </div>
29
+ </MacOSWindowFrame>
34
30
  )
35
31
  }