@gram-ai/elements 1.27.3 → 1.27.5

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 (278) hide show
  1. package/README.md +72 -60
  2. package/README.typedoc.md +6 -6
  3. package/bin/cli.js +74 -74
  4. package/dist/compat-shims-CO9JXXV4.cjs.map +1 -1
  5. package/dist/{compat-shims-BPJ7Q68c.js → compat-shims-DxtUrORi.js} +4 -2
  6. package/dist/compat-shims-DxtUrORi.js.map +1 -0
  7. package/dist/components/ShareButton/index.d.ts +2 -2
  8. package/dist/components/assistant-ui/message-feedback.d.ts +1 -1
  9. package/dist/components/assistant-ui/tooltip-icon-button.d.ts +2 -2
  10. package/dist/components/ui/avatar.d.ts +2 -2
  11. package/dist/components/ui/button.d.ts +1 -1
  12. package/dist/components/ui/calendar.d.ts +1 -1
  13. package/dist/components/ui/collapsible.d.ts +1 -1
  14. package/dist/components/ui/dialog.d.ts +4 -4
  15. package/dist/components/ui/popover.d.ts +2 -2
  16. package/dist/components/ui/skeleton.d.ts +1 -1
  17. package/dist/components/ui/time-range-picker.d.ts +4 -2
  18. package/dist/components/ui/tool-ui.d.ts +7 -7
  19. package/dist/components/ui/tooltip.d.ts +2 -2
  20. package/dist/contexts/ConnectionStatusContext.d.ts +1 -1
  21. package/dist/elements.cjs +1 -1
  22. package/dist/elements.css +1 -1
  23. package/dist/elements.js +2 -2
  24. package/dist/hooks/useDensity.d.ts +73 -73
  25. package/dist/hooks/useMCPTools.d.ts +1 -1
  26. package/dist/hooks/useRadius.d.ts +1 -1
  27. package/dist/{index-BpJstUh1.cjs → index-C4bFBGfl.cjs} +4 -4
  28. package/dist/{index-BpJstUh1.cjs.map → index-C4bFBGfl.cjs.map} +1 -1
  29. package/dist/{index-CUitXazZ.js → index-D93pV0_o.js} +55 -55
  30. package/dist/{index-CUitXazZ.js.map → index-D93pV0_o.js.map} +1 -1
  31. package/dist/{index-DBrhzauj.js → index-DuCQRbcQ.js} +6386 -6337
  32. package/dist/index-DuCQRbcQ.js.map +1 -0
  33. package/dist/{index-DxfW52oA.cjs → index-y_PNN5vK.cjs} +64 -46
  34. package/dist/index-y_PNN5vK.cjs.map +1 -0
  35. package/dist/lib/cassette.d.ts +4 -4
  36. package/dist/lib/errorTracking.d.ts +1 -1
  37. package/dist/lib/messageConverter.d.ts +1 -1
  38. package/dist/lib/models.d.ts +1 -1
  39. package/dist/plugins/chart/ui/bar-chart.d.ts +1 -1
  40. package/dist/plugins/generative-ui/ui/accordion-wrapper.d.ts +2 -2
  41. package/dist/plugins/generative-ui/ui/accordion.d.ts +1 -1
  42. package/dist/plugins/generative-ui/ui/action-button.d.ts +2 -2
  43. package/dist/plugins/generative-ui/ui/alert-wrapper.d.ts +1 -1
  44. package/dist/plugins/generative-ui/ui/alert.d.ts +4 -4
  45. package/dist/plugins/generative-ui/ui/avatar.d.ts +5 -5
  46. package/dist/plugins/generative-ui/ui/badge.d.ts +2 -2
  47. package/dist/plugins/generative-ui/ui/button-wrapper.d.ts +2 -2
  48. package/dist/plugins/generative-ui/ui/button.d.ts +2 -2
  49. package/dist/plugins/generative-ui/ui/card-wrapper.d.ts +2 -2
  50. package/dist/plugins/generative-ui/ui/card.d.ts +8 -8
  51. package/dist/plugins/generative-ui/ui/checkbox.d.ts +1 -1
  52. package/dist/plugins/generative-ui/ui/data-table.d.ts +2 -2
  53. package/dist/plugins/generative-ui/ui/dialog.d.ts +3 -3
  54. package/dist/plugins/generative-ui/ui/dropdown-menu.d.ts +3 -3
  55. package/dist/plugins/generative-ui/ui/grid.d.ts +3 -3
  56. package/dist/plugins/generative-ui/ui/input-wrapper.d.ts +1 -1
  57. package/dist/plugins/generative-ui/ui/input.d.ts +2 -2
  58. package/dist/plugins/generative-ui/ui/label.d.ts +1 -1
  59. package/dist/plugins/generative-ui/ui/metric.d.ts +3 -3
  60. package/dist/plugins/generative-ui/ui/pagination.d.ts +6 -6
  61. package/dist/plugins/generative-ui/ui/popover.d.ts +4 -4
  62. package/dist/plugins/generative-ui/ui/progress.d.ts +2 -2
  63. package/dist/plugins/generative-ui/ui/radio-group.d.ts +1 -1
  64. package/dist/plugins/generative-ui/ui/select.d.ts +2 -2
  65. package/dist/plugins/generative-ui/ui/separator.d.ts +1 -1
  66. package/dist/plugins/generative-ui/ui/skeleton.d.ts +1 -1
  67. package/dist/plugins/generative-ui/ui/stack.d.ts +6 -6
  68. package/dist/plugins/generative-ui/ui/switch.d.ts +2 -2
  69. package/dist/plugins/generative-ui/ui/table.d.ts +9 -9
  70. package/dist/plugins/generative-ui/ui/tabs-wrapper.d.ts +1 -1
  71. package/dist/plugins/generative-ui/ui/tabs.d.ts +1 -1
  72. package/dist/plugins/generative-ui/ui/text.d.ts +3 -3
  73. package/dist/plugins/generative-ui/ui/textarea.d.ts +2 -2
  74. package/dist/plugins/generative-ui/ui/tooltip.d.ts +1 -1
  75. package/dist/plugins.cjs +1 -1
  76. package/dist/plugins.js +1 -1
  77. package/dist/{profiler-D6ndqfsd.js → profiler-FpBY9eRv.js} +2 -2
  78. package/dist/{profiler-D6ndqfsd.js.map → profiler-FpBY9eRv.js.map} +1 -1
  79. package/dist/{profiler-DhnzZ34c.cjs → profiler-_mthyjvo.cjs} +2 -2
  80. package/dist/{profiler-DhnzZ34c.cjs.map → profiler-_mthyjvo.cjs.map} +1 -1
  81. package/dist/react-shim.js +1 -1
  82. package/dist/server/express.cjs.map +1 -1
  83. package/dist/server/express.js.map +1 -1
  84. package/dist/{startRecording-BwXmdmy1.cjs → startRecording-NJcpiHw-.cjs} +2 -2
  85. package/dist/{startRecording-BwXmdmy1.cjs.map → startRecording-NJcpiHw-.cjs.map} +1 -1
  86. package/dist/{startRecording-B_9CRZ_P.js → startRecording-r5MXQ2Dm.js} +2 -2
  87. package/dist/{startRecording-B_9CRZ_P.js.map → startRecording-r5MXQ2Dm.js.map} +1 -1
  88. package/dist/types/index.d.ts +2 -2
  89. package/package.json +1 -5
  90. package/src/compat-plugin.ts +14 -14
  91. package/src/compat-shims.ts +33 -31
  92. package/src/compat.test.ts +48 -48
  93. package/src/compat.ts +6 -6
  94. package/src/components/Chat/index.tsx +17 -17
  95. package/src/components/Chat/stories/Charts.stories.tsx +98 -98
  96. package/src/components/Chat/stories/Composer.stories.tsx +15 -15
  97. package/src/components/Chat/stories/ConnectionConfiguration.stories.tsx +44 -44
  98. package/src/components/Chat/stories/CustomComponents.stories.tsx +17 -17
  99. package/src/components/Chat/stories/Density.stories.tsx +20 -20
  100. package/src/components/Chat/stories/ErrorBoundary.stories.tsx +47 -47
  101. package/src/components/Chat/stories/FrontendTools.stories.tsx +39 -39
  102. package/src/components/Chat/stories/GenerativeUI.stories.tsx +48 -48
  103. package/src/components/Chat/stories/MessageFeedback.stories.tsx +52 -52
  104. package/src/components/Chat/stories/Modal.stories.tsx +28 -28
  105. package/src/components/Chat/stories/Model.stories.tsx +11 -11
  106. package/src/components/Chat/stories/Radius.stories.tsx +20 -20
  107. package/src/components/Chat/stories/Sidecar.stories.tsx +13 -13
  108. package/src/components/Chat/stories/StyleIsolation.stories.tsx +11 -11
  109. package/src/components/Chat/stories/Theme.stories.tsx +25 -25
  110. package/src/components/Chat/stories/Thread.stories.tsx +25 -25
  111. package/src/components/Chat/stories/ToolApproval.stories.tsx +55 -55
  112. package/src/components/Chat/stories/ToolMentions.stories.tsx +17 -17
  113. package/src/components/Chat/stories/Tools.stories.tsx +88 -88
  114. package/src/components/Chat/stories/Variants.stories.tsx +32 -32
  115. package/src/components/Chat/stories/Welcome.stories.tsx +14 -14
  116. package/src/components/ChatHistory.tsx +7 -7
  117. package/src/components/FrontendTools/index.tsx +5 -5
  118. package/src/components/Replay.stories.tsx +157 -157
  119. package/src/components/Replay.tsx +76 -73
  120. package/src/components/ShadowRoot.tsx +40 -40
  121. package/src/components/ShareButton/index.tsx +32 -32
  122. package/src/components/assistant-ui/assistant-modal.tsx +92 -87
  123. package/src/components/assistant-ui/assistant-sidecar.tsx +35 -35
  124. package/src/components/assistant-ui/attachment.tsx +80 -80
  125. package/src/components/assistant-ui/connection-status-indicator.tsx +33 -33
  126. package/src/components/assistant-ui/error-boundary.tsx +34 -34
  127. package/src/components/assistant-ui/follow-on-suggestions.tsx +26 -26
  128. package/src/components/assistant-ui/markdown-text.tsx +69 -69
  129. package/src/components/assistant-ui/mentioned-tools-badges.tsx +38 -38
  130. package/src/components/assistant-ui/message-feedback.tsx +74 -61
  131. package/src/components/assistant-ui/reasoning.tsx +83 -83
  132. package/src/components/assistant-ui/thread-list.tsx +45 -45
  133. package/src/components/assistant-ui/thread.tsx +278 -278
  134. package/src/components/assistant-ui/tool-fallback.tsx +37 -37
  135. package/src/components/assistant-ui/tool-group.tsx +26 -26
  136. package/src/components/assistant-ui/tool-mention-autocomplete.tsx +122 -122
  137. package/src/components/assistant-ui/tooltip-icon-button.tsx +18 -18
  138. package/src/components/ui/avatar.tsx +12 -12
  139. package/src/components/ui/button.tsx +12 -12
  140. package/src/components/ui/buttonVariants.ts +17 -17
  141. package/src/components/ui/calendar.tsx +106 -106
  142. package/src/components/ui/charts.stories.tsx +56 -56
  143. package/src/components/ui/collapsible.tsx +5 -5
  144. package/src/components/ui/dialog.tsx +30 -30
  145. package/src/components/ui/generative-ui.stories.tsx +200 -200
  146. package/src/components/ui/generative-ui.tsx +26 -26
  147. package/src/components/ui/popover.tsx +14 -14
  148. package/src/components/ui/skeleton.tsx +5 -5
  149. package/src/components/ui/time-range-picker.stories.tsx +80 -80
  150. package/src/components/ui/time-range-picker.tsx +272 -235
  151. package/src/components/ui/tool-ui.stories.tsx +37 -37
  152. package/src/components/ui/tool-ui.tsx +221 -215
  153. package/src/components/ui/tooltip.tsx +15 -15
  154. package/src/constants/tailwind.ts +1 -1
  155. package/src/contexts/ChatIdContext.tsx +7 -7
  156. package/src/contexts/ConnectionStatusContext.tsx +64 -64
  157. package/src/contexts/ElementsProvider.tsx +222 -211
  158. package/src/contexts/ReplayContext.ts +3 -3
  159. package/src/contexts/ToolApprovalContext.tsx +54 -54
  160. package/src/contexts/ToolExecutionContext.tsx +34 -34
  161. package/src/contexts/contexts.ts +7 -7
  162. package/src/contexts/portal-container-context.ts +2 -2
  163. package/src/contexts/portal-container.tsx +7 -7
  164. package/src/embedded.ts +1 -1
  165. package/src/global.css +25 -25
  166. package/src/hooks/useAuth.ts +72 -72
  167. package/src/hooks/useDensity.ts +79 -79
  168. package/src/hooks/useElements.ts +6 -6
  169. package/src/hooks/useExpanded.ts +12 -12
  170. package/src/hooks/useFollowOnSuggestions.ts +87 -82
  171. package/src/hooks/useGramThreadListAdapter.tsx +99 -99
  172. package/src/hooks/useMCPTools.ts +47 -47
  173. package/src/hooks/useModel.ts +14 -14
  174. package/src/hooks/usePluginComponents.ts +11 -11
  175. package/src/hooks/usePortalContainer.ts +5 -5
  176. package/src/hooks/useRadius.ts +23 -23
  177. package/src/hooks/useRecordCassette.ts +34 -34
  178. package/src/hooks/useSession.ts +11 -11
  179. package/src/hooks/useThemeProps.ts +13 -13
  180. package/src/hooks/useThreadId.ts +4 -4
  181. package/src/hooks/useToolApproval.ts +7 -7
  182. package/src/hooks/useToolMentions.ts +40 -40
  183. package/src/index.ts +26 -26
  184. package/src/lib/api.test.ts +61 -61
  185. package/src/lib/api.ts +4 -3
  186. package/src/lib/auth.ts +13 -13
  187. package/src/lib/cassette.ts +84 -84
  188. package/src/lib/easing.ts +1 -1
  189. package/src/lib/errorTracking.config.ts +5 -5
  190. package/src/lib/errorTracking.ts +29 -29
  191. package/src/lib/generative-ui.ts +7 -7
  192. package/src/lib/humanize.ts +3 -3
  193. package/src/lib/messageConverter.test.ts +130 -127
  194. package/src/lib/messageConverter.ts +196 -196
  195. package/src/lib/models.ts +21 -20
  196. package/src/lib/token.test.ts +56 -56
  197. package/src/lib/token.ts +14 -14
  198. package/src/lib/tool-mentions.ts +45 -45
  199. package/src/lib/tools.ts +66 -62
  200. package/src/lib/utils.ts +5 -5
  201. package/src/lib.d.ts +1 -1
  202. package/src/plugins/README.md +5 -5
  203. package/src/plugins/chart/catalog.ts +18 -18
  204. package/src/plugins/chart/chart.test.ts +31 -31
  205. package/src/plugins/chart/component.tsx +34 -34
  206. package/src/plugins/chart/index.ts +4 -4
  207. package/src/plugins/chart/ui/area-chart.tsx +42 -42
  208. package/src/plugins/chart/ui/bar-chart.tsx +46 -46
  209. package/src/plugins/chart/ui/donut-chart.tsx +48 -48
  210. package/src/plugins/chart/ui/index.ts +7 -7
  211. package/src/plugins/chart/ui/line-chart.tsx +43 -43
  212. package/src/plugins/chart/ui/pie-chart.tsx +44 -44
  213. package/src/plugins/chart/ui/radar-chart.tsx +33 -33
  214. package/src/plugins/chart/ui/scatter-chart.tsx +43 -43
  215. package/src/plugins/components/MacOSWindowFrame.tsx +15 -15
  216. package/src/plugins/components/PluginLoadingState.tsx +10 -10
  217. package/src/plugins/components/index.ts +1 -1
  218. package/src/plugins/generative-ui/catalog.ts +54 -54
  219. package/src/plugins/generative-ui/component.tsx +85 -85
  220. package/src/plugins/generative-ui/index.ts +4 -4
  221. package/src/plugins/generative-ui/ui/accordion-wrapper.tsx +16 -16
  222. package/src/plugins/generative-ui/ui/accordion.tsx +16 -16
  223. package/src/plugins/generative-ui/ui/action-button.tsx +28 -28
  224. package/src/plugins/generative-ui/ui/alert-wrapper.tsx +8 -8
  225. package/src/plugins/generative-ui/ui/alert.tsx +20 -20
  226. package/src/plugins/generative-ui/ui/avatar-wrapper.tsx +7 -7
  227. package/src/plugins/generative-ui/ui/avatar.tsx +30 -30
  228. package/src/plugins/generative-ui/ui/badge.tsx +22 -22
  229. package/src/plugins/generative-ui/ui/button-wrapper.tsx +12 -12
  230. package/src/plugins/generative-ui/ui/button.tsx +28 -28
  231. package/src/plugins/generative-ui/ui/card-wrapper.tsx +8 -8
  232. package/src/plugins/generative-ui/ui/card.tsx +27 -27
  233. package/src/plugins/generative-ui/ui/checkbox-wrapper.tsx +9 -9
  234. package/src/plugins/generative-ui/ui/checkbox.tsx +9 -9
  235. package/src/plugins/generative-ui/ui/data-table.tsx +8 -8
  236. package/src/plugins/generative-ui/ui/dialog.tsx +31 -31
  237. package/src/plugins/generative-ui/ui/dropdown-menu.tsx +44 -44
  238. package/src/plugins/generative-ui/ui/grid.tsx +12 -12
  239. package/src/plugins/generative-ui/ui/index.ts +40 -40
  240. package/src/plugins/generative-ui/ui/input-wrapper.tsx +11 -11
  241. package/src/plugins/generative-ui/ui/input.tsx +9 -9
  242. package/src/plugins/generative-ui/ui/label.tsx +8 -8
  243. package/src/plugins/generative-ui/ui/list.tsx +11 -11
  244. package/src/plugins/generative-ui/ui/metric.tsx +23 -23
  245. package/src/plugins/generative-ui/ui/pagination.tsx +28 -28
  246. package/src/plugins/generative-ui/ui/popover.tsx +21 -21
  247. package/src/plugins/generative-ui/ui/progress.tsx +13 -13
  248. package/src/plugins/generative-ui/ui/radio-group.tsx +12 -12
  249. package/src/plugins/generative-ui/ui/select-wrapper.tsx +7 -7
  250. package/src/plugins/generative-ui/ui/select.tsx +37 -37
  251. package/src/plugins/generative-ui/ui/separator.tsx +9 -9
  252. package/src/plugins/generative-ui/ui/skeleton-wrapper.tsx +10 -10
  253. package/src/plugins/generative-ui/ui/skeleton.tsx +5 -5
  254. package/src/plugins/generative-ui/ui/stack.tsx +28 -28
  255. package/src/plugins/generative-ui/ui/switch.tsx +11 -11
  256. package/src/plugins/generative-ui/ui/table.tsx +32 -32
  257. package/src/plugins/generative-ui/ui/tabs-wrapper.tsx +11 -11
  258. package/src/plugins/generative-ui/ui/tabs.tsx +26 -26
  259. package/src/plugins/generative-ui/ui/text.tsx +12 -12
  260. package/src/plugins/generative-ui/ui/textarea.tsx +7 -7
  261. package/src/plugins/generative-ui/ui/tooltip.tsx +12 -12
  262. package/src/plugins/index.ts +7 -7
  263. package/src/react-shim.ts +6 -6
  264. package/src/server/bun.ts +12 -12
  265. package/src/server/core.ts +25 -25
  266. package/src/server/express.ts +17 -15
  267. package/src/server/fastify.ts +14 -14
  268. package/src/server/hono.ts +9 -9
  269. package/src/server/nextjs.ts +12 -12
  270. package/src/server/tanstack-start.ts +12 -12
  271. package/src/server.ts +27 -27
  272. package/src/storybook.d.ts +4 -4
  273. package/src/types/index.ts +122 -122
  274. package/src/types/plugins.ts +7 -7
  275. package/src/vite-env.d.ts +12 -12
  276. package/dist/compat-shims-BPJ7Q68c.js.map +0 -1
  277. package/dist/index-DBrhzauj.js.map +0 -1
  278. package/dist/index-DxfW52oA.cjs.map +0 -1
package/src/lib/utils.ts CHANGED
@@ -1,16 +1,16 @@
1
- import { clsx, type ClassValue } from 'clsx'
2
- import { twMerge } from 'tailwind-merge'
1
+ import { clsx, type ClassValue } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
3
 
4
4
  export function cn(...inputs: ClassValue[]) {
5
- return twMerge(clsx(inputs))
5
+ return twMerge(clsx(inputs));
6
6
  }
7
7
 
8
8
  export function assertNever(value: unknown): never {
9
- throw new Error(`Unexpected value: ${value}`)
9
+ throw new Error(`Unexpected value: ${value}`);
10
10
  }
11
11
 
12
12
  export function assert(condition: unknown, message: string): asserts condition {
13
13
  if (!condition) {
14
- throw new Error(message)
14
+ throw new Error(message);
15
15
  }
16
16
  }
package/src/lib.d.ts CHANGED
@@ -1 +1 @@
1
- type FIXME<T, S extends string> = (T & S) | T
1
+ type FIXME<T, S extends string> = (T & S) | T;
@@ -19,19 +19,19 @@ A plugin is defined by the following TypeScript interface:
19
19
  ```typescript
20
20
  interface Plugin {
21
21
  // The language identifier for the code fence (e.g., "vega", "mermaid", "d3")
22
- language: string
22
+ language: string;
23
23
 
24
24
  // Instructions for the LLM on how to use this plugin
25
- prompt: string
25
+ prompt: string;
26
26
 
27
27
  // Your custom React component that renders the code block
28
- SyntaxHighlighter: ComponentType<SyntaxHighlighterProps>
28
+ SyntaxHighlighter: ComponentType<SyntaxHighlighterProps>;
29
29
 
30
30
  // Optional: Custom header component for the code block
31
- CodeHeader?: ComponentType<CodeHeaderProps> | null
31
+ CodeHeader?: ComponentType<CodeHeaderProps> | null;
32
32
 
33
33
  // Optional: Whether to override existing plugins with the same language
34
- overrideExisting?: boolean
34
+ overrideExisting?: boolean;
35
35
  }
36
36
  ```
37
37
 
@@ -1,5 +1,5 @@
1
- import { createCatalog } from '@json-render/core'
2
- import { z } from 'zod'
1
+ import { createCatalog } from "@json-render/core";
2
+ import { z } from "zod";
3
3
 
4
4
  /**
5
5
  * Data point schema - common structure for all chart types
@@ -8,7 +8,7 @@ const dataPointSchema = z.object({
8
8
  label: z.string(),
9
9
  value: z.number(),
10
10
  color: z.string().optional(),
11
- })
11
+ });
12
12
 
13
13
  /**
14
14
  * Multi-series data point for line/area charts
@@ -17,7 +17,7 @@ const seriesDataPointSchema = z
17
17
  .object({
18
18
  label: z.string(),
19
19
  })
20
- .catchall(z.number())
20
+ .catchall(z.number());
21
21
 
22
22
  /**
23
23
  * Chart Catalog
@@ -26,19 +26,19 @@ const seriesDataPointSchema = z
26
26
  * Uses Recharts under the hood for rendering.
27
27
  */
28
28
  export const chartCatalog = createCatalog({
29
- name: 'chart',
29
+ name: "chart",
30
30
  components: {
31
31
  BarChart: {
32
32
  props: z.object({
33
33
  title: z.string().optional(),
34
34
  data: z.array(dataPointSchema),
35
- layout: z.enum(['vertical', 'horizontal']).optional(),
35
+ layout: z.enum(["vertical", "horizontal"]).optional(),
36
36
  showGrid: z.boolean().optional(),
37
37
  showLegend: z.boolean().optional(),
38
38
  className: z.string().optional(),
39
39
  }),
40
40
  description:
41
- 'Bar chart for comparing categorical data. Use vertical for few categories, horizontal for many or long labels.',
41
+ "Bar chart for comparing categorical data. Use vertical for few categories, horizontal for many or long labels.",
42
42
  },
43
43
 
44
44
  LineChart: {
@@ -53,7 +53,7 @@ export const chartCatalog = createCatalog({
53
53
  className: z.string().optional(),
54
54
  }),
55
55
  description:
56
- 'Line chart for showing trends over time or continuous data. Supports multiple series.',
56
+ "Line chart for showing trends over time or continuous data. Supports multiple series.",
57
57
  },
58
58
 
59
59
  AreaChart: {
@@ -67,7 +67,7 @@ export const chartCatalog = createCatalog({
67
67
  className: z.string().optional(),
68
68
  }),
69
69
  description:
70
- 'Area chart for showing volume/magnitude over time. Use stacked for part-to-whole relationships.',
70
+ "Area chart for showing volume/magnitude over time. Use stacked for part-to-whole relationships.",
71
71
  },
72
72
 
73
73
  PieChart: {
@@ -79,7 +79,7 @@ export const chartCatalog = createCatalog({
79
79
  className: z.string().optional(),
80
80
  }),
81
81
  description:
82
- 'Pie chart for showing proportions of a whole. Best for 2-6 categories.',
82
+ "Pie chart for showing proportions of a whole. Best for 2-6 categories.",
83
83
  },
84
84
 
85
85
  DonutChart: {
@@ -93,7 +93,7 @@ export const chartCatalog = createCatalog({
93
93
  className: z.string().optional(),
94
94
  }),
95
95
  description:
96
- 'Donut chart (pie with center hole). Good for showing a key metric in the center.',
96
+ "Donut chart (pie with center hole). Good for showing a key metric in the center.",
97
97
  },
98
98
 
99
99
  ScatterChart: {
@@ -106,7 +106,7 @@ export const chartCatalog = createCatalog({
106
106
  label: z.string().optional(),
107
107
  size: z.number().optional(),
108
108
  color: z.string().optional(),
109
- })
109
+ }),
110
110
  ),
111
111
  xLabel: z.string().optional(),
112
112
  yLabel: z.string().optional(),
@@ -114,7 +114,7 @@ export const chartCatalog = createCatalog({
114
114
  className: z.string().optional(),
115
115
  }),
116
116
  description:
117
- 'Scatter plot for showing correlation between two variables.',
117
+ "Scatter plot for showing correlation between two variables.",
118
118
  },
119
119
 
120
120
  RadarChart: {
@@ -125,17 +125,17 @@ export const chartCatalog = createCatalog({
125
125
  className: z.string().optional(),
126
126
  }),
127
127
  description:
128
- 'Radar/spider chart for comparing multiple attributes. Best for 3-8 dimensions.',
128
+ "Radar/spider chart for comparing multiple attributes. Best for 3-8 dimensions.",
129
129
  },
130
130
  },
131
- })
131
+ });
132
132
 
133
133
  export type ChartCatalogComponentProps = typeof chartCatalog extends {
134
- components: infer C
134
+ components: infer C;
135
135
  }
136
136
  ? {
137
137
  [K in keyof C]: C[K] extends { props: infer P }
138
138
  ? z.infer<P extends z.ZodType ? P : never>
139
- : never
139
+ : never;
140
140
  }
141
- : never
141
+ : never;
@@ -1,66 +1,66 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { parse, View, Warn } from 'vega'
3
- import { expressionInterpreter } from 'vega-interpreter'
1
+ import { describe, it, expect } from "vitest";
2
+ import { parse, View, Warn } from "vega";
3
+ import { expressionInterpreter } from "vega-interpreter";
4
4
 
5
- describe('ChartRenderer CSP compliance', () => {
6
- it('renders a chart using vega-interpreter without eval', async () => {
5
+ describe("ChartRenderer CSP compliance", () => {
6
+ it("renders a chart using vega-interpreter without eval", async () => {
7
7
  const spec = {
8
- $schema: 'https://vega.github.io/schema/vega/v5.json',
8
+ $schema: "https://vega.github.io/schema/vega/v5.json",
9
9
  width: 400,
10
10
  height: 200,
11
11
  data: [
12
12
  {
13
- name: 'table',
13
+ name: "table",
14
14
  values: [
15
- { category: 'A', amount: 28 },
16
- { category: 'B', amount: 55 },
15
+ { category: "A", amount: 28 },
16
+ { category: "B", amount: 55 },
17
17
  ],
18
18
  },
19
19
  ],
20
20
  marks: [
21
21
  {
22
- type: 'rect',
23
- from: { data: 'table' },
22
+ type: "rect",
23
+ from: { data: "table" },
24
24
  encode: {
25
25
  enter: {
26
- x: { scale: 'xscale', field: 'category' },
27
- width: { scale: 'xscale', band: 1 },
28
- y: { scale: 'yscale', field: 'amount' },
29
- y2: { scale: 'yscale', value: 0 },
26
+ x: { scale: "xscale", field: "category" },
27
+ width: { scale: "xscale", band: 1 },
28
+ y: { scale: "yscale", field: "amount" },
29
+ y2: { scale: "yscale", value: 0 },
30
30
  },
31
31
  },
32
32
  },
33
33
  ],
34
34
  scales: [
35
35
  {
36
- name: 'xscale',
37
- type: 'band',
38
- domain: { data: 'table', field: 'category' },
39
- range: 'width',
36
+ name: "xscale",
37
+ type: "band",
38
+ domain: { data: "table", field: "category" },
39
+ range: "width",
40
40
  },
41
41
  {
42
- name: 'yscale',
43
- domain: { data: 'table', field: 'amount' },
44
- range: 'height',
42
+ name: "yscale",
43
+ domain: { data: "table", field: "amount" },
44
+ range: "height",
45
45
  },
46
46
  ],
47
- }
47
+ };
48
48
 
49
49
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
- const runtime = parse(spec as any, undefined, { ast: true })
50
+ const runtime = parse(spec as any, undefined, { ast: true });
51
51
 
52
52
  // This is the key - using expr: vegaInterpreter means no eval() is called
53
53
  const view = new View(runtime, {
54
- renderer: 'none',
54
+ renderer: "none",
55
55
  logLevel: Warn,
56
56
  expr: expressionInterpreter,
57
- })
57
+ });
58
58
 
59
- await view.runAsync()
59
+ await view.runAsync();
60
60
 
61
61
  // If we get here without error, CSP compliance works
62
- expect(view.data('table')).toHaveLength(2)
62
+ expect(view.data("table")).toHaveLength(2);
63
63
 
64
- view.finalize()
65
- })
66
- })
64
+ view.finalize();
65
+ });
66
+ });
@@ -1,13 +1,13 @@
1
- 'use client'
1
+ "use client";
2
2
 
3
- import { useDensity } from '@/hooks/useDensity'
4
- import { cn } from '@/lib/utils'
5
- import { isJsonRenderTree, type JsonRenderNode } from '@/lib/generative-ui'
6
- import { SyntaxHighlighterProps } from '@assistant-ui/react-markdown'
7
- import { AlertCircleIcon } from 'lucide-react'
8
- import { FC, useMemo } from 'react'
9
- import { MacOSWindowFrame } from '../components/MacOSWindowFrame'
10
- import { PluginLoadingState } from '../components/PluginLoadingState'
3
+ import { useDensity } from "@/hooks/useDensity";
4
+ import { cn } from "@/lib/utils";
5
+ import { isJsonRenderTree, type JsonRenderNode } from "@/lib/generative-ui";
6
+ import { SyntaxHighlighterProps } from "@assistant-ui/react-markdown";
7
+ import { AlertCircleIcon } from "lucide-react";
8
+ import { FC, useMemo } from "react";
9
+ import { MacOSWindowFrame } from "../components/MacOSWindowFrame";
10
+ import { PluginLoadingState } from "../components/PluginLoadingState";
11
11
 
12
12
  // Import all chart components
13
13
  import {
@@ -18,17 +18,17 @@ import {
18
18
  DonutChart,
19
19
  ScatterChart,
20
20
  RadarChart,
21
- } from './ui'
21
+ } from "./ui";
22
22
 
23
23
  const loadingMessages = [
24
- 'Rendering chart...',
25
- 'Visualizing data...',
26
- 'Building chart...',
27
- 'Processing data...',
28
- ]
24
+ "Rendering chart...",
25
+ "Visualizing data...",
26
+ "Building chart...",
27
+ "Processing data...",
28
+ ];
29
29
 
30
30
  function getRandomLoadingMessage() {
31
- return loadingMessages[Math.floor(Math.random() * loadingMessages.length)]
31
+ return loadingMessages[Math.floor(Math.random() * loadingMessages.length)];
32
32
  }
33
33
 
34
34
  /**
@@ -43,61 +43,61 @@ const chartComponents: Record<string, FC<any>> = {
43
43
  DonutChart,
44
44
  ScatterChart,
45
45
  RadarChart,
46
- }
46
+ };
47
47
 
48
48
  /**
49
49
  * Render a chart node from json-render tree
50
50
  */
51
51
  function renderChartNode(node: JsonRenderNode): React.ReactNode {
52
- const Component = chartComponents[node.type]
52
+ const Component = chartComponents[node.type];
53
53
 
54
54
  if (!Component) {
55
55
  return (
56
- <div className="text-muted-foreground flex items-center gap-2 text-sm">
56
+ <div className="flex items-center gap-2 text-sm text-muted-foreground">
57
57
  <AlertCircleIcon className="size-4" />
58
58
  <span>Unknown chart type: {node.type}</span>
59
59
  </div>
60
- )
60
+ );
61
61
  }
62
62
 
63
- return <Component {...(node.props ?? {})} />
63
+ return <Component {...(node.props ?? {})} />;
64
64
  }
65
65
 
66
66
  export const ChartRenderer: FC<SyntaxHighlighterProps> = ({ code }) => {
67
- const d = useDensity()
67
+ const d = useDensity();
68
68
 
69
69
  // Parse JSON - returns null if invalid (still streaming)
70
70
  const content = useMemo(() => {
71
- const trimmedCode = code.trim()
72
- if (!trimmedCode) return null
71
+ const trimmedCode = code.trim();
72
+ if (!trimmedCode) return null;
73
73
 
74
74
  try {
75
- const parsed = JSON.parse(trimmedCode)
75
+ const parsed = JSON.parse(trimmedCode);
76
76
  // Validate it has a type field (basic json-render structure)
77
77
  if (!isJsonRenderTree(parsed)) {
78
- return null
78
+ return null;
79
79
  }
80
- return parsed
80
+ return parsed;
81
81
  } catch {
82
82
  // JSON is incomplete (still streaming) - return null to show loading state
83
- return null
83
+ return null;
84
84
  }
85
- }, [code])
85
+ }, [code]);
86
86
 
87
87
  // Memoize the loading message so it doesn't change on every render
88
- const loadingMessage = useMemo(() => getRandomLoadingMessage(), [])
88
+ const loadingMessage = useMemo(() => getRandomLoadingMessage(), []);
89
89
 
90
90
  // Show loading shimmer while JSON is incomplete/streaming
91
91
  if (!content) {
92
- return <PluginLoadingState text={loadingMessage} />
92
+ return <PluginLoadingState text={loadingMessage} />;
93
93
  }
94
94
 
95
95
  // Render with macOS-style window frame
96
96
  return (
97
97
  <MacOSWindowFrame>
98
- <div className={cn('bg-card w-full', d('p-lg'))}>
98
+ <div className={cn("w-full bg-card", d("p-lg"))}>
99
99
  {renderChartNode(content)}
100
100
  </div>
101
101
  </MacOSWindowFrame>
102
- )
103
- }
102
+ );
103
+ };
@@ -1,11 +1,11 @@
1
- import { Plugin } from '@/types/plugins'
2
- import { ChartRenderer } from './component'
1
+ import { Plugin } from "@/types/plugins";
2
+ import { ChartRenderer } from "./component";
3
3
 
4
4
  /**
5
5
  * This plugin renders charts using json-render format.
6
6
  */
7
7
  export const chart: Plugin = {
8
- language: 'chart',
8
+ language: "chart",
9
9
  prompt: `WHEN TO USE CHARTS:
10
10
  Create charts to visualize numerical data when it helps users understand patterns, trends, or comparisons. Use the 'chart' code block format.
11
11
 
@@ -158,4 +158,4 @@ CONTENT GUIDELINES:
158
158
  - Focus on what the data means, not how it's displayed`,
159
159
  Component: ChartRenderer,
160
160
  Header: undefined,
161
- }
161
+ };
@@ -1,7 +1,7 @@
1
- 'use client'
1
+ "use client";
2
2
 
3
- import { cn } from '@/lib/utils'
4
- import { FC, useMemo } from 'react'
3
+ import { cn } from "@/lib/utils";
4
+ import { FC, useMemo } from "react";
5
5
  import {
6
6
  AreaChart as RechartsAreaChart,
7
7
  Area,
@@ -12,12 +12,12 @@ import {
12
12
  Legend,
13
13
  ResponsiveContainer,
14
14
  TooltipProps,
15
- } from 'recharts'
15
+ } from "recharts";
16
16
 
17
17
  const CustomTooltip = ({ active, payload }: TooltipProps<number, string>) => {
18
- if (!active || !payload || payload.length === 0) return null
18
+ if (!active || !payload || payload.length === 0) return null;
19
19
  return (
20
- <div className="bg-background text-foreground border-border rounded-md border px-2 py-1.5 text-xs shadow-sm">
20
+ <div className="rounded-md border border-border bg-background px-2 py-1.5 text-xs text-foreground shadow-sm">
21
21
  {payload.map((entry, index) => (
22
22
  <div key={index} className="flex items-center gap-2">
23
23
  <span
@@ -26,37 +26,37 @@ const CustomTooltip = ({ active, payload }: TooltipProps<number, string>) => {
26
26
  />
27
27
  <span>{entry.name}:</span>
28
28
  <span className="font-medium">
29
- {typeof entry.value === 'number'
29
+ {typeof entry.value === "number"
30
30
  ? entry.value.toLocaleString()
31
31
  : entry.value}
32
32
  </span>
33
33
  </div>
34
34
  ))}
35
35
  </div>
36
- )
37
- }
36
+ );
37
+ };
38
38
 
39
39
  const COLORS = [
40
- 'var(--chart-1)',
41
- 'var(--chart-2)',
42
- 'var(--chart-3)',
43
- 'var(--chart-4)',
44
- 'var(--chart-5)',
45
- ]
40
+ "var(--chart-1)",
41
+ "var(--chart-2)",
42
+ "var(--chart-3)",
43
+ "var(--chart-4)",
44
+ "var(--chart-5)",
45
+ ];
46
46
 
47
47
  interface SeriesDataPoint {
48
- label: string
49
- [key: string]: string | number
48
+ label: string;
49
+ [key: string]: string | number;
50
50
  }
51
51
 
52
52
  export interface AreaChartProps {
53
- title?: string
54
- data: SeriesDataPoint[]
55
- series?: string[]
56
- stacked?: boolean
57
- showGrid?: boolean
58
- showLegend?: boolean
59
- className?: string
53
+ title?: string;
54
+ data: SeriesDataPoint[];
55
+ series?: string[];
56
+ stacked?: boolean;
57
+ showGrid?: boolean;
58
+ showLegend?: boolean;
59
+ className?: string;
60
60
  }
61
61
 
62
62
  export const AreaChart: FC<AreaChartProps> = ({
@@ -70,16 +70,16 @@ export const AreaChart: FC<AreaChartProps> = ({
70
70
  }) => {
71
71
  // Auto-detect series from data keys if not provided
72
72
  const seriesKeys = useMemo(() => {
73
- if (series && series.length > 0) return series
74
- if (data.length === 0) return []
75
- const keys = Object.keys(data[0]).filter((k) => k !== 'label')
76
- return keys
77
- }, [data, series])
73
+ if (series && series.length > 0) return series;
74
+ if (data.length === 0) return [];
75
+ const keys = Object.keys(data[0]).filter((k) => k !== "label");
76
+ return keys;
77
+ }, [data, series]);
78
78
 
79
79
  return (
80
- <div className={cn('flex flex-col gap-2', className)}>
80
+ <div className={cn("flex flex-col gap-2", className)}>
81
81
  {title && (
82
- <h3 className="text-foreground text-sm font-medium">{title}</h3>
82
+ <h3 className="text-sm font-medium text-foreground">{title}</h3>
83
83
  )}
84
84
  <div className="h-[250px] w-full">
85
85
  <ResponsiveContainer width="100%" height="100%">
@@ -95,21 +95,21 @@ export const AreaChart: FC<AreaChartProps> = ({
95
95
  )}
96
96
  <XAxis
97
97
  dataKey="label"
98
- tick={{ fill: 'var(--foreground)', fontSize: 12 }}
99
- axisLine={{ stroke: 'var(--border)' }}
100
- tickLine={{ stroke: 'var(--border)' }}
98
+ tick={{ fill: "var(--foreground)", fontSize: 12 }}
99
+ axisLine={{ stroke: "var(--border)" }}
100
+ tickLine={{ stroke: "var(--border)" }}
101
101
  />
102
102
  <YAxis
103
- tick={{ fill: 'var(--foreground)', fontSize: 12 }}
104
- axisLine={{ stroke: 'var(--border)' }}
105
- tickLine={{ stroke: 'var(--border)' }}
103
+ tick={{ fill: "var(--foreground)", fontSize: 12 }}
104
+ axisLine={{ stroke: "var(--border)" }}
105
+ tickLine={{ stroke: "var(--border)" }}
106
106
  />
107
107
  <Tooltip content={<CustomTooltip />} />
108
108
  {showLegend && seriesKeys.length > 1 && (
109
109
  <Legend
110
- wrapperStyle={{ color: 'var(--foreground)' }}
110
+ wrapperStyle={{ color: "var(--foreground)" }}
111
111
  formatter={(value) => (
112
- <span style={{ color: 'var(--foreground)' }}>{value}</span>
112
+ <span style={{ color: "var(--foreground)" }}>{value}</span>
113
113
  )}
114
114
  />
115
115
  )}
@@ -118,7 +118,7 @@ export const AreaChart: FC<AreaChartProps> = ({
118
118
  key={key}
119
119
  type="monotone"
120
120
  dataKey={key}
121
- stackId={stacked ? 'stack' : undefined}
121
+ stackId={stacked ? "stack" : undefined}
122
122
  stroke={COLORS[index % COLORS.length]}
123
123
  fill={COLORS[index % COLORS.length]}
124
124
  fillOpacity={0.3}
@@ -129,5 +129,5 @@ export const AreaChart: FC<AreaChartProps> = ({
129
129
  </ResponsiveContainer>
130
130
  </div>
131
131
  </div>
132
- )
133
- }
132
+ );
133
+ };