@gram-ai/elements 1.9.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -80,7 +80,6 @@ const config: ElementsConfig = {
80
80
  },
81
81
  composer: {
82
82
  placeholder: 'Ask me anything...',
83
- attachments: true,
84
83
  },
85
84
  modal: {
86
85
  defaultOpen: true,
@@ -102,19 +101,22 @@ The `ElementsConfig` object accepts the following configuration options:
102
101
 
103
102
  ### Top-Level Configuration
104
103
 
105
- | Property | Type | Required | Status | Default | Description |
106
- | -------------- | ---------------------------------------------------------- | -------- | ---------------------- | --------------------- | --------------------------------------------------------------------------------------------------- |
107
- | `projectSlug` | `string` | Yes | ✅ Implemented | - | The project slug to use for the Elements library |
108
- | `mcp` | `string` | Yes | ✅ Implemented | - | The Gram Server URL. Can be retrieved from `https://app.getgram.ai/{team}/{project}/mcp/{mcp_slug}` |
109
- | `chatEndpoint` | `string` | No | ✅ Implemented | `'/chat/completions'` | The path of your backend's chat endpoint |
110
- | `environment` | `Record<string, unknown>` | No | ✅ Implemented | `undefined` | Custom environment variable overrides for the MCP server |
111
- | `variant` | `'widget' \| 'standalone'` | No | ✅ Implemented | `undefined` | Whether to render the chat window inside an expandable modal or as a standalone chat window |
112
- | `theme` | `'light' \| 'dark' \| 'system'` | No | ⚠️ Not yet implemented | `undefined` | The theme to use for the Elements library |
113
- | `welcome` | [`WelcomeConfig`](#welcome-configuration-welcomeconfig) | Yes | ✅ Implemented | - | Configuration for the welcome message and initial suggestions |
114
- | `composer` | [`ComposerConfig`](#composer-configuration-composerconfig) | No | ✅ Implemented | `undefined` | Configuration for the composer input |
115
- | `modal` | [`ModalConfig`](#modal-configuration-modalconfig) | No | ✅ Implemented | `undefined` | Configuration for the modal window (only applies when `variant` is `'widget'`) |
116
- | `model` | [`ModelConfig`](#model-configuration-modelconfig) | No | ✅ Implemented | `undefined` | LLM model configuration |
117
- | `tools` | [`ToolsConfig`](#tools-configuration-toolsconfig) | No | ✅ Implemented | `undefined` | Configuration for custom tool components |
104
+ | Property | Type | Required | Status | Default | Description |
105
+ | -------------- | ---------------------------------------------------------- | -------- | -------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
106
+ | `systemPrompt` | `string` | No | ✅ Implemented | `undefined` | The system prompt to use for the Elements library |
107
+ | `projectSlug` | `string` | Yes | ✅ Implemented | - | The project slug to use for the Elements library |
108
+ | `mcp` | `string` | Yes | ✅ Implemented | - | The Gram Server URL. Can be retrieved from `https://app.getgram.ai/{team}/{project}/mcp/{mcp_slug}` |
109
+ | `chatEndpoint` | `string` | No | ✅ Implemented | `'/chat/completions'` | The path of your backend's chat endpoint |
110
+ | `environment` | `Record<string, unknown>` | No | ✅ Implemented | `undefined` | Custom environment variable overrides for the MCP server. See [Gram documentation](https://www.speakeasy.com/docs/gram/host-mcp/public-private-servers#pass-through-authentication) for pass-through authentication |
111
+ | `variant` | `'widget' \| 'sidecar' \| 'standalone'` | No | Implemented | `'widget'` | The layout variant for the chat interface. `widget` is a popup modal, `sidecar` is a side panel, `standalone` is a full-page experience |
112
+ | `plugins` | [`Plugin[]`](#plugins) | No | ✅ Implemented | `[]` | Array of plugins to extend rendering capabilities. See [Plugins section](#plugins) for details |
113
+ | `theme` | [`ThemeConfig`](#theme-configuration-themeconfig) | No | ✅ Implemented | `undefined` | Visual appearance configuration options |
114
+ | `welcome` | [`WelcomeConfig`](#welcome-configuration-welcomeconfig) | Yes | ✅ Implemented | - | Configuration for the welcome message and initial suggestions |
115
+ | `composer` | [`ComposerConfig`](#composer-configuration-composerconfig) | No | ✅ Implemented | `undefined` | Configuration for the composer input |
116
+ | `modal` | [`ModalConfig`](#modal-configuration-modalconfig) | No | ✅ Implemented | `undefined` | Configuration for the modal window (does not apply if variant is `'standalone'`) |
117
+ | `sidecar` | [`SidecarConfig`](#sidecar-configuration-sidecarconfig) | No | ✅ Implemented | `undefined` | Configuration for the sidecar panel (only applies if variant is `'sidecar'`) |
118
+ | `model` | [`ModelConfig`](#model-configuration-modelconfig) | No | ✅ Implemented | `undefined` | LLM model configuration |
119
+ | `tools` | [`ToolsConfig`](#tools-configuration-toolsconfig) | No | ✅ Implemented | `undefined` | Configuration for custom tool components |
118
120
 
119
121
  ### Welcome Configuration (`WelcomeConfig`)
120
122
 
@@ -134,18 +136,53 @@ The `ElementsConfig` object accepts the following configuration options:
134
136
 
135
137
  ### Composer Configuration (`ComposerConfig`)
136
138
 
137
- | Property | Type | Required | Status | Default | Description |
138
- | ------------- | --------- | -------- | ---------------------- | ------- | --------------------------------------------- |
139
- | `placeholder` | `string` | Yes | ✅ Implemented | - | The placeholder text for the composer input |
140
- | `attachments` | `boolean` | Yes | ⚠️ Not yet implemented | - | Whether to enable attachments in the composer |
139
+ | Property | Type | Required | Status | Default | Description |
140
+ | ------------- | -------------------------------------------------------------------------------- | -------- | ---------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
141
+ | `placeholder` | `string` | No | ✅ Implemented | `'Send a message...'` | The placeholder text for the composer input |
142
+ | `attachments` | `boolean \| `[`AttachmentsConfig`](#attachments-configuration-attachmentsconfig) | No | ⚠️ Not yet implemented | `true` | Configuration for file attachments. Set to `false` to disable, `true` for defaults, or provide an object for fine-grained control |
143
+
144
+ #### Attachments Configuration (`AttachmentsConfig`)
145
+
146
+ | Property | Type | Required | Status | Default | Description |
147
+ | ---------- | ---------- | -------- | ---------------------- | ----------- | --------------------------------------------------------------------------- |
148
+ | `accept` | `string[]` | No | ⚠️ Not yet implemented | `undefined` | Accepted file types (MIME types or extensions), e.g., `['image/*', '.pdf']` |
149
+ | `maxCount` | `number` | No | ⚠️ Not yet implemented | `10` | Maximum number of files that can be attached at once |
150
+ | `maxSize` | `number` | No | ⚠️ Not yet implemented | `104857600` | Maximum file size in bytes (default: 100MB) |
141
151
 
142
152
  ### Modal Configuration (`ModalConfig`)
143
153
 
144
- | Property | Type | Required | Status | Default | Description |
145
- | ------------- | ------------------------------------------------------- | -------- | -------------- | ----------- | ------------------------------------------------------------ |
146
- | `defaultOpen` | `boolean` | No | ✅ Implemented | `false` | Whether to open the modal window by default |
147
- | `icon` | `(state: 'open' \| 'closed' \| undefined) => ReactNode` | No | ✅ Implemented | `undefined` | Custom icon component function that receives the modal state |
148
- | `className` | `string` | No | ✅ Implemented | `undefined` | Additional CSS class name to apply to the modal window |
154
+ | Property | Type | Required | Status | Default | Description |
155
+ | ------------- | ----------------------------------------------------------------------------------- | -------- | -------------- | ---------------- | ------------------------------------------------------------ |
156
+ | `defaultOpen` | `boolean` | No | ✅ Implemented | `false` | Whether to open the modal window by default |
157
+ | `title` | `string` | No | ✅ Implemented | `'Chat'` | The title displayed in the modal header |
158
+ | `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | No | ✅ Implemented | `'bottom-right'` | The position of the modal trigger button |
159
+ | `icon` | `(state: 'open' \| 'closed' \| undefined) => ReactNode` | No | ✅ Implemented | `undefined` | Custom icon component function that receives the modal state |
160
+ | `expandable` | `boolean` | No | ✅ Implemented | `false` | Whether the modal can be expanded to full screen |
161
+ | `dimensions` | `{ default: ModalDimension, expanded?: Pick<ModalDimension, 'width' \| 'height'> }` | No | ✅ Implemented | `undefined` | The dimensions for default and expanded states of the modal |
162
+
163
+ #### Modal Dimension Object
164
+
165
+ | Property | Type | Description |
166
+ | ----------- | ------------------------ | -------------------------------------- |
167
+ | `width` | `number \| '${number}%'` | Width of the modal |
168
+ | `height` | `number \| '${number}%'` | Height of the modal |
169
+ | `maxHeight` | `number \| '${number}%'` | Maximum height of the modal (optional) |
170
+
171
+ ### Sidecar Configuration (`SidecarConfig`)
172
+
173
+ | Property | Type | Required | Status | Default | Description |
174
+ | --------------- | ---------------------------------- | -------- | -------------- | --------- | -------------------------------------------- |
175
+ | `title` | `string` | No | ✅ Implemented | `'Chat'` | The title displayed in the sidecar header |
176
+ | `width` | `string \| number \| '${number}%'` | No | ✅ Implemented | `'400px'` | The width of the sidecar panel |
177
+ | `expandedWidth` | `string \| number \| '${number}%'` | No | ✅ Implemented | `'800px'` | The width of the sidecar panel when expanded |
178
+
179
+ ### Theme Configuration (`ThemeConfig`)
180
+
181
+ | Property | Type | Required | Status | Default | Description |
182
+ | ------------- | ------------------------------------- | -------- | -------------- | ---------- | --------------------------------------------------------------------------------------- |
183
+ | `colorScheme` | `'light' \| 'dark' \| 'system'` | No | ✅ Implemented | `'light'` | The color scheme to use for the UI |
184
+ | `density` | `'compact' \| 'normal' \| 'spacious'` | No | ✅ Implemented | `'normal'` | Determines the overall spacing. `compact` reduces padding, `spacious` increases padding |
185
+ | `radius` | `'round' \| 'soft' \| 'sharp'` | No | ✅ Implemented | `'soft'` | Determines the overall roundness. `round` is large radius, `sharp` is minimal radius |
149
186
 
150
187
  ### Model Configuration (`ModelConfig`)
151
188
 
@@ -204,14 +241,21 @@ const config: ElementsConfig = {
204
241
 
205
242
  ```typescript
206
243
  import { ElementsConfig } from '@gram-ai/elements'
244
+ import { recommended } from '@gram-ai/elements/plugins'
207
245
  import { WeatherComponent } from './components/WeatherComponent'
208
246
 
209
247
  const config: ElementsConfig = {
248
+ systemPrompt: 'You are a helpful AI assistant.',
210
249
  projectSlug: 'my-project',
211
250
  mcp: 'https://app.getgram.ai/mcp/my-mcp-slug',
212
251
  chatEndpoint: '/api/chat',
213
252
  variant: 'widget',
214
- theme: 'system',
253
+ plugins: recommended,
254
+ theme: {
255
+ colorScheme: 'system',
256
+ density: 'normal',
257
+ radius: 'soft',
258
+ },
215
259
  environment: {
216
260
  API_KEY: 'your-api-key',
217
261
  BASE_URL: 'https://api.example.com',
@@ -234,11 +278,23 @@ const config: ElementsConfig = {
234
278
  },
235
279
  composer: {
236
280
  placeholder: 'Type your message...',
237
- attachments: true,
238
281
  },
239
282
  modal: {
240
283
  defaultOpen: false,
241
- className: 'custom-modal-class',
284
+ title: 'AI Assistant',
285
+ position: 'bottom-right',
286
+ expandable: true,
287
+ dimensions: {
288
+ default: {
289
+ width: 400,
290
+ height: 600,
291
+ maxHeight: '90%',
292
+ },
293
+ expanded: {
294
+ width: '90%',
295
+ height: '90%',
296
+ },
297
+ },
242
298
  },
243
299
  model: {
244
300
  showModelPicker: true,
@@ -288,7 +344,6 @@ const config: ElementsConfig = {
288
344
  },
289
345
  composer: {
290
346
  placeholder: 'Ask me anything...',
291
- attachments: true,
292
347
  },
293
348
  model: {
294
349
  showModelPicker: true,
@@ -297,6 +352,132 @@ const config: ElementsConfig = {
297
352
  }
298
353
  ```
299
354
 
355
+ #### Sidecar Variant with Custom Theme
356
+
357
+ ```typescript
358
+ import { ElementsConfig } from '@gram-ai/elements'
359
+
360
+ const config: ElementsConfig = {
361
+ projectSlug: 'my-project',
362
+ mcp: 'https://app.getgram.ai/mcp/my-mcp-slug',
363
+ variant: 'sidecar',
364
+ theme: {
365
+ colorScheme: 'dark',
366
+ density: 'compact',
367
+ radius: 'round',
368
+ },
369
+ welcome: {
370
+ title: 'Support Chat',
371
+ subtitle: "We're here to help",
372
+ },
373
+ sidecar: {
374
+ title: 'Customer Support',
375
+ width: '450px',
376
+ expandedWidth: '900px',
377
+ },
378
+ }
379
+ ```
380
+
381
+ ## Plugins
382
+
383
+ Plugins extend the Gram Elements library with custom rendering capabilities for specific content types. They allow you to transform markdown code blocks into rich, interactive visualizations and components.
384
+
385
+ ### How Plugins Work
386
+
387
+ When you add a plugin:
388
+
389
+ 1. The plugin extends the system prompt with instructions for the LLM
390
+ 2. The LLM returns code blocks marked with the plugin's language identifier
391
+ 3. The plugin's custom component renders the code block content
392
+
393
+ For example, the built-in chart plugin instructs the LLM to return Vega specifications for visualizations, which are then rendered as interactive charts.
394
+
395
+ ### Using Recommended Plugins
396
+
397
+ Gram Elements includes a set of recommended plugins that you can use out of the box:
398
+
399
+ ```typescript
400
+ import { GramElementsProvider, Chat, type ElementsConfig } from '@gram-ai/elements'
401
+ import { recommended } from '@gram-ai/elements/plugins'
402
+ import '@gram-ai/elements/elements.css'
403
+
404
+ const config: ElementsConfig = {
405
+ projectSlug: 'my-project',
406
+ mcp: 'https://app.getgram.ai/mcp/my-mcp-slug',
407
+ welcome: {
408
+ title: 'Hello!',
409
+ subtitle: 'How can I help you today?',
410
+ },
411
+ // Add all recommended plugins
412
+ plugins: recommended,
413
+ }
414
+
415
+ export const App = () => {
416
+ return (
417
+ <GramElementsProvider config={config}>
418
+ <Chat />
419
+ </GramElementsProvider>
420
+ )
421
+ }
422
+ ```
423
+
424
+ #### Available Recommended Plugins
425
+
426
+ - **`chart`** - Renders Vega chart specifications as interactive visualizations
427
+
428
+ ### Using Individual Plugins
429
+
430
+ You can also import and use plugins individually:
431
+
432
+ ```typescript
433
+ import { chart } from '@gram-ai/elements/plugins'
434
+
435
+ const config: ElementsConfig = {
436
+ // ... other config
437
+ plugins: [chart],
438
+ }
439
+ ```
440
+
441
+ ### Using Custom Plugins
442
+
443
+ You can create your own custom plugins to add specialized rendering capabilities:
444
+
445
+ ```typescript
446
+ import { GramElementsProvider, Chat, type ElementsConfig } from '@gram-ai/elements'
447
+ import { chart } from '@gram-ai/elements/plugins'
448
+ import { myCustomPlugin } from './plugins/myCustomPlugin'
449
+ import '@gram-ai/elements/elements.css'
450
+
451
+ const config: ElementsConfig = {
452
+ projectSlug: 'my-project',
453
+ mcp: 'https://app.getgram.ai/mcp/my-mcp-slug',
454
+ welcome: {
455
+ title: 'Hello!',
456
+ subtitle: 'How can I help you today?',
457
+ },
458
+ // Combine built-in and custom plugins
459
+ plugins: [chart, myCustomPlugin],
460
+ }
461
+
462
+ export const App = () => {
463
+ return (
464
+ <GramElementsProvider config={config}>
465
+ <Chat />
466
+ </GramElementsProvider>
467
+ )
468
+ }
469
+ ```
470
+
471
+ ### Creating Custom Plugins
472
+
473
+ To create your own plugins, see the comprehensive [Plugin Development Guide](./src/plugins/README.md). The guide covers:
474
+
475
+ - Plugin architecture and interface
476
+ - Step-by-step tutorial for creating plugins
477
+ - Best practices and common patterns
478
+ - Real-world examples
479
+ - Troubleshooting tips
480
+
300
481
  ## Contributing
301
482
 
302
483
  We welcome pull requests to Elements. Please read the contributing guide.
@@ -1,7 +1,7 @@
1
1
  import { VariantProps } from 'class-variance-authority';
2
2
  import * as React from 'react';
3
3
  declare const Button: React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLButtonElement> & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
4
- variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
4
+ variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
5
5
  size?: "default" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg" | null | undefined;
6
6
  } & import('class-variance-authority/types').ClassProp) | undefined) => string> & {
7
7
  asChild?: boolean;
@@ -1,4 +1,4 @@
1
1
  export declare const buttonVariants: (props?: ({
2
- variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
2
+ variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
3
3
  size?: "default" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg" | null | undefined;
4
4
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;