@gram-ai/elements 1.8.3 → 1.9.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.
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Density class mappings for different UI elements
3
+ */
4
+ declare const densityClasses: {
5
+ readonly compact: {
6
+ readonly 'p-sm': "p-1";
7
+ readonly 'p-md': "p-2";
8
+ readonly 'p-lg': "p-3";
9
+ readonly 'p-xl': "p-4";
10
+ readonly 'px-sm': "px-2";
11
+ readonly 'px-md': "px-3";
12
+ readonly 'px-lg': "px-4";
13
+ readonly 'px-xl': "px-5";
14
+ readonly 'py-sm': "py-1";
15
+ readonly 'py-md': "py-1.5";
16
+ readonly 'py-lg': "py-2";
17
+ readonly 'py-xl': "py-3";
18
+ readonly 'gap-sm': "gap-1";
19
+ readonly 'gap-md': "gap-2";
20
+ readonly 'gap-lg': "gap-3";
21
+ readonly 'gap-xl': "gap-4";
22
+ readonly 'h-header': "h-10";
23
+ readonly 'h-input': "min-h-12";
24
+ readonly 'text-base': "text-sm";
25
+ readonly 'text-title': "text-xl";
26
+ readonly 'text-subtitle': "text-sm";
27
+ };
28
+ readonly normal: {
29
+ readonly 'p-sm': "p-2";
30
+ readonly 'p-md': "p-4";
31
+ readonly 'p-lg': "p-6";
32
+ readonly 'p-xl': "p-8";
33
+ readonly 'px-sm': "px-3";
34
+ readonly 'px-md': "px-4";
35
+ readonly 'px-lg': "px-6";
36
+ readonly 'px-xl': "px-8";
37
+ readonly 'py-sm': "py-1.5";
38
+ readonly 'py-md': "py-2.5";
39
+ readonly 'py-lg': "py-5";
40
+ readonly 'py-xl': "py-8";
41
+ readonly 'gap-sm': "gap-1";
42
+ readonly 'gap-md': "gap-2";
43
+ readonly 'gap-lg': "gap-3";
44
+ readonly 'gap-xl': "gap-5";
45
+ readonly 'h-header': "h-12";
46
+ readonly 'h-input': "min-h-16";
47
+ readonly 'text-base': "text-base";
48
+ readonly 'text-title': "text-2xl";
49
+ readonly 'text-subtitle': "text-base";
50
+ };
51
+ readonly spacious: {
52
+ readonly 'p-sm': "p-3";
53
+ readonly 'p-md': "p-6";
54
+ readonly 'p-lg': "p-8";
55
+ readonly 'p-xl': "p-10";
56
+ readonly 'px-sm': "px-4";
57
+ readonly 'px-md': "px-6";
58
+ readonly 'px-lg': "px-8";
59
+ readonly 'px-xl': "px-10";
60
+ readonly 'py-sm': "py-2";
61
+ readonly 'py-md': "py-4";
62
+ readonly 'py-lg': "py-6";
63
+ readonly 'py-xl': "py-10";
64
+ readonly 'gap-sm': "gap-2";
65
+ readonly 'gap-md': "gap-3";
66
+ readonly 'gap-lg': "gap-4";
67
+ readonly 'gap-xl': "gap-6";
68
+ readonly 'h-header': "h-14";
69
+ readonly 'h-input': "min-h-20";
70
+ readonly 'text-base': "text-lg";
71
+ readonly 'text-title': "text-3xl";
72
+ readonly 'text-subtitle': "text-lg";
73
+ };
74
+ };
75
+ type DensityToken = keyof (typeof densityClasses)['normal'];
76
+ /**
77
+ * Hook to get density classes based on theme config
78
+ * Use: const d = useDensity(); then d('p-md') returns the appropriate padding class
79
+ */
80
+ export declare const useDensity: () => (token: DensityToken) => "p-1" | "p-2" | "p-3" | "p-4" | "px-2" | "px-3" | "px-4" | "px-5" | "py-1" | "py-1.5" | "py-2" | "py-3" | "gap-1" | "gap-2" | "gap-3" | "gap-4" | "h-10" | "min-h-12" | "text-sm" | "text-xl" | "p-6" | "p-8" | "px-6" | "px-8" | "py-2.5" | "py-5" | "py-8" | "gap-5" | "h-12" | "min-h-16" | "text-base" | "text-2xl" | "p-10" | "px-10" | "py-4" | "py-6" | "py-10" | "gap-6" | "h-14" | "min-h-20" | "text-lg" | "text-3xl";
81
+ export {};
@@ -0,0 +1,8 @@
1
+ import { Dispatch, SetStateAction } from 'react';
2
+ interface UseExpandedAPI {
3
+ expandable: boolean;
4
+ isExpanded: boolean;
5
+ setIsExpanded: Dispatch<SetStateAction<boolean>>;
6
+ }
7
+ export declare const useExpanded: () => UseExpandedAPI;
8
+ export {};
@@ -0,0 +1,7 @@
1
+ type RadiusSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
2
+ /**
3
+ * Hook to get radius classes based on theme config
4
+ * Use: const r = useRadius(); then r('lg') returns the appropriate rounded class
5
+ */
6
+ export declare const useRadius: () => (size: RadiusSize) => string;
7
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Hook to get theme-related props including dark mode class
3
+ */
4
+ export declare const useThemeProps: () => {
5
+ readonly className: "dark" | undefined;
6
+ };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { ElementsProvider as GramElementsProvider } from './contexts/ElementsProvider';
2
2
  export { useElements as useGramElements } from './hooks/useElements';
3
3
  export { Chat } from './components/Chat';
4
- export type { ElementsConfig, ComposerConfig, ModalConfig, ToolsConfig, ModelConfig, WelcomeConfig, Suggestion, Model, ModalTriggerPosition, } from './types';
4
+ export { ToolUI, ToolUISection } from './components/ui/tool-ui';
5
+ export type { ToolUIProps, ToolUISectionProps, ToolStatus, } from './components/ui/tool-ui';
6
+ export type { ElementsConfig, ComposerConfig, AttachmentsConfig, ModalConfig, SidecarConfig, ToolsConfig, ModelConfig, ThemeConfig, WelcomeConfig, Suggestion, Model, ModalTriggerPosition, } from './types';
@@ -0,0 +1 @@
1
+ export declare const EASE_OUT_QUINT: readonly [0.23, 1, 0.32, 1];
@@ -1,2 +1,3 @@
1
1
  import { ClassValue } from 'clsx';
2
2
  export declare function cn(...inputs: ClassValue[]): string;
3
+ export declare function assertNever(value: unknown): never;
@@ -1,6 +1,6 @@
1
1
  import { MODELS } from '../lib/models';
2
2
  import { ToolCallMessagePartComponent } from '@assistant-ui/react';
3
- import { ReactNode } from 'react';
3
+ import { Dispatch, SetStateAction, ReactNode } from 'react';
4
4
  import { z } from 'zod';
5
5
  export interface ElementsProviderProps {
6
6
  /**
@@ -13,6 +13,8 @@ export interface ElementsProviderProps {
13
13
  config: ElementsConfig;
14
14
  }
15
15
  type ServerUrl = string;
16
+ export declare const VARIANTS: readonly ["widget", "sidecar", "standalone"];
17
+ export type Variant = (typeof VARIANTS)[number];
16
18
  export interface ElementsConfig {
17
19
  /**
18
20
  * The system prompt to use for the Elements library.
@@ -46,9 +48,15 @@ export interface ElementsConfig {
46
48
  */
47
49
  environment?: Record<string, unknown>;
48
50
  /**
49
- * Whether to render the chat window inside of an expandable modal or a standalone chat window.
51
+ * The layout variant for the chat interface.
52
+ *
53
+ * - `widget`: A popup modal anchored to the bottom-right corner (default)
54
+ * - `sidecar`: A side panel that slides in from the right edge of the screen
55
+ * - `standalone`: A full-page chat experience
56
+ *
57
+ * @default 'widget'
50
58
  */
51
- variant?: 'widget' | 'standalone';
59
+ variant?: Variant;
52
60
  /**
53
61
  * LLM model configuration.
54
62
  *
@@ -62,11 +70,10 @@ export interface ElementsConfig {
62
70
  */
63
71
  model?: ModelConfig;
64
72
  /**
65
- * The theme to use for the Elements library.
66
- *
67
- * TODO: Not yet implemented
73
+ * Visual appearance configuration options.
74
+ * Similar to OpenAI ChatKit's ThemeOption.
68
75
  */
69
- theme?: 'light' | 'dark' | 'system';
76
+ theme?: ThemeConfig;
70
77
  /**
71
78
  * The configuration for the welcome message and initial suggestions.
72
79
  */
@@ -80,6 +87,11 @@ export interface ElementsConfig {
80
87
  * Does not apply if variant is 'standalone'.
81
88
  */
82
89
  modal?: ModalConfig;
90
+ /**
91
+ * The configuration for the sidecar panel.
92
+ * Only applies if variant is 'sidecar'.
93
+ */
94
+ sidecar?: SidecarConfig;
83
95
  /**
84
96
  * The configuration for the tools.
85
97
  */
@@ -100,6 +112,48 @@ export interface ModelConfig {
100
112
  */
101
113
  defaultModel?: Model;
102
114
  }
115
+ export declare const DENSITIES: readonly ["compact", "normal", "spacious"];
116
+ export type Density = (typeof DENSITIES)[number];
117
+ export declare const COLOR_SCHEMES: readonly ["light", "dark", "system"];
118
+ export type ColorScheme = (typeof COLOR_SCHEMES)[number];
119
+ export declare const RADII: readonly ["round", "soft", "sharp"];
120
+ export type Radius = (typeof RADII)[number];
121
+ /**
122
+ * ThemeConfig provides visual appearance customization options.
123
+ * Inspired by OpenAI ChatKit's ThemeOption.
124
+ *
125
+ * @example
126
+ * const config: ElementsConfig = {
127
+ * theme: {
128
+ * colorScheme: 'dark',
129
+ * density: 'compact',
130
+ * radius: 'round',
131
+ * },
132
+ * }
133
+ */
134
+ export interface ThemeConfig {
135
+ /**
136
+ * The color scheme to use for the UI.
137
+ * @default 'light'
138
+ */
139
+ colorScheme?: ColorScheme;
140
+ /**
141
+ * Determines the overall spacing of the UI.
142
+ * - `compact`: Reduced padding and margins for dense layouts
143
+ * - `normal`: Standard spacing (default)
144
+ * - `spacious`: Increased padding and margins for airy layouts
145
+ * @default 'normal'
146
+ */
147
+ density?: Density;
148
+ /**
149
+ * Determines the overall roundness of the UI.
150
+ * - `round`: Large border radius
151
+ * - `soft`: Moderate border radius (default)
152
+ * - `sharp`: Minimal border radius
153
+ * @default 'soft'
154
+ */
155
+ radius?: Radius;
156
+ }
103
157
  /**
104
158
  * ToolsConfig is used to configure tool support in the Elements library.
105
159
  * At the moment, you can override the default React components used by
@@ -162,6 +216,11 @@ export interface ModalConfig {
162
216
  * Whether to open the modal window by default.
163
217
  */
164
218
  defaultOpen?: boolean;
219
+ /**
220
+ * The title displayed in the modal header.
221
+ * @default 'Chat'
222
+ */
223
+ title?: string;
165
224
  /**
166
225
  * The position of the modal trigger
167
226
  *
@@ -194,21 +253,72 @@ export interface ModalConfig {
194
253
  export interface ComposerConfig {
195
254
  /**
196
255
  * The placeholder text for the composer input.
256
+ * @default 'Send a message...'
197
257
  */
198
- placeholder: string;
258
+ placeholder?: string;
199
259
  /**
200
- * Whether to enable attachments in the composer.
201
- *
202
- * NOTE: Not yet implemented
260
+ * Configuration for file attachments in the composer.
261
+ * Set to `false` to disable attachments entirely.
262
+ * Set to `true` for default attachment behavior.
263
+ * Or provide an object for fine-grained control.
264
+ * @default true
265
+ */
266
+ attachments?: boolean | AttachmentsConfig;
267
+ }
268
+ /**
269
+ * AttachmentsConfig provides fine-grained control over file attachments.
270
+ * Inspired by OpenAI ChatKit's attachment options.
271
+ */
272
+ export interface AttachmentsConfig {
273
+ /**
274
+ * Accepted file types. Can be MIME types or file extensions.
275
+ * @example ['image/*', '.pdf', '.docx']
276
+ */
277
+ accept?: string[];
278
+ /**
279
+ * Maximum number of files that can be attached at once.
280
+ * @default 10
281
+ */
282
+ maxCount?: number;
283
+ /**
284
+ * Maximum file size in bytes.
285
+ * @default 104857600 (100MB)
286
+ */
287
+ maxSize?: number;
288
+ }
289
+ export interface SidecarConfig {
290
+ /**
291
+ * The title displayed in the sidecar header.
292
+ * @default 'Chat'
293
+ */
294
+ title?: string;
295
+ /**
296
+ * The width of the sidecar panel.
297
+ * @default '400px'
298
+ */
299
+ width?: string | number | `${number}%`;
300
+ /**
301
+ * The width of the sidecar panel when expanded.
302
+ * @default '800px'
303
+ */
304
+ expandedWidth?: string | number | `${number}%`;
305
+ /**
306
+ * Callback when the pop-out button is clicked.
307
+ * If provided, the pop-out button will be shown.
308
+ */
309
+ onPopOut?: () => void;
310
+ /**
311
+ * Callback when the collapse button is clicked.
312
+ * If provided, the collapse button will be shown.
203
313
  */
204
- attachments: boolean;
314
+ onCollapse?: () => void;
205
315
  }
206
316
  export type ElementsContextType = {
207
317
  config: ElementsConfig;
208
318
  setModel: (model: Model) => void;
209
319
  model: Model;
210
320
  isExpanded: boolean;
211
- setIsExpanded: (isExpanded: boolean) => void;
321
+ setIsExpanded: Dispatch<SetStateAction<boolean>>;
212
322
  isOpen: boolean;
213
323
  setIsOpen: (isOpen: boolean) => void;
214
324
  };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@gram-ai/elements",
3
3
  "description": "Gram Elements is a library of UI primitives for building chat-like experiences for MCP Servers.",
4
4
  "type": "module",
5
- "version": "1.8.3",
5
+ "version": "1.9.0",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
8
8
  ".": {