@gram-ai/elements 1.8.4 → 1.10.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, ColorScheme, Radius, Density, Variant, } 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,7 +1,6 @@
1
1
  import { MODELS } from '../lib/models';
2
2
  import { ToolCallMessagePartComponent } from '@assistant-ui/react';
3
- import { ReactNode } from 'react';
4
- import { z } from 'zod';
3
+ import { Dispatch, SetStateAction, ReactNode } from 'react';
5
4
  export interface ElementsProviderProps {
6
5
  /**
7
6
  * The children to render.
@@ -13,6 +12,8 @@ export interface ElementsProviderProps {
13
12
  config: ElementsConfig;
14
13
  }
15
14
  type ServerUrl = string;
15
+ export declare const VARIANTS: readonly ["widget", "sidecar", "standalone"];
16
+ export type Variant = (typeof VARIANTS)[number];
16
17
  export interface ElementsConfig {
17
18
  /**
18
19
  * The system prompt to use for the Elements library.
@@ -46,9 +47,15 @@ export interface ElementsConfig {
46
47
  */
47
48
  environment?: Record<string, unknown>;
48
49
  /**
49
- * Whether to render the chat window inside of an expandable modal or a standalone chat window.
50
+ * The layout variant for the chat interface.
51
+ *
52
+ * - `widget`: A popup modal anchored to the bottom-right corner (default)
53
+ * - `sidecar`: A side panel that slides in from the right edge of the screen
54
+ * - `standalone`: A full-page chat experience
55
+ *
56
+ * @default 'widget'
50
57
  */
51
- variant?: 'widget' | 'standalone';
58
+ variant?: Variant;
52
59
  /**
53
60
  * LLM model configuration.
54
61
  *
@@ -62,11 +69,10 @@ export interface ElementsConfig {
62
69
  */
63
70
  model?: ModelConfig;
64
71
  /**
65
- * The theme to use for the Elements library.
66
- *
67
- * TODO: Not yet implemented
72
+ * Visual appearance configuration options.
73
+ * Similar to OpenAI ChatKit's ThemeOption.
68
74
  */
69
- theme?: 'light' | 'dark' | 'system';
75
+ theme?: ThemeConfig;
70
76
  /**
71
77
  * The configuration for the welcome message and initial suggestions.
72
78
  */
@@ -80,6 +86,11 @@ export interface ElementsConfig {
80
86
  * Does not apply if variant is 'standalone'.
81
87
  */
82
88
  modal?: ModalConfig;
89
+ /**
90
+ * The configuration for the sidecar panel.
91
+ * Only applies if variant is 'sidecar'.
92
+ */
93
+ sidecar?: SidecarConfig;
83
94
  /**
84
95
  * The configuration for the tools.
85
96
  */
@@ -100,6 +111,48 @@ export interface ModelConfig {
100
111
  */
101
112
  defaultModel?: Model;
102
113
  }
114
+ export declare const DENSITIES: readonly ["compact", "normal", "spacious"];
115
+ export type Density = (typeof DENSITIES)[number];
116
+ export declare const COLOR_SCHEMES: readonly ["light", "dark", "system"];
117
+ export type ColorScheme = (typeof COLOR_SCHEMES)[number];
118
+ export declare const RADII: readonly ["round", "soft", "sharp"];
119
+ export type Radius = (typeof RADII)[number];
120
+ /**
121
+ * ThemeConfig provides visual appearance customization options.
122
+ * Inspired by OpenAI ChatKit's ThemeOption.
123
+ *
124
+ * @example
125
+ * const config: ElementsConfig = {
126
+ * theme: {
127
+ * colorScheme: 'dark',
128
+ * density: 'compact',
129
+ * radius: 'round',
130
+ * },
131
+ * }
132
+ */
133
+ export interface ThemeConfig {
134
+ /**
135
+ * The color scheme to use for the UI.
136
+ * @default 'light'
137
+ */
138
+ colorScheme?: ColorScheme;
139
+ /**
140
+ * Determines the overall spacing of the UI.
141
+ * - `compact`: Reduced padding and margins for dense layouts
142
+ * - `normal`: Standard spacing (default)
143
+ * - `spacious`: Increased padding and margins for airy layouts
144
+ * @default 'normal'
145
+ */
146
+ density?: Density;
147
+ /**
148
+ * Determines the overall roundness of the UI.
149
+ * - `round`: Large border radius
150
+ * - `soft`: Moderate border radius (default)
151
+ * - `sharp`: Minimal border radius
152
+ * @default 'soft'
153
+ */
154
+ radius?: Radius;
155
+ }
103
156
  /**
104
157
  * ToolsConfig is used to configure tool support in the Elements library.
105
158
  * At the moment, you can override the default React components used by
@@ -162,6 +215,11 @@ export interface ModalConfig {
162
215
  * Whether to open the modal window by default.
163
216
  */
164
217
  defaultOpen?: boolean;
218
+ /**
219
+ * The title displayed in the modal header.
220
+ * @default 'Chat'
221
+ */
222
+ title?: string;
165
223
  /**
166
224
  * The position of the modal trigger
167
225
  *
@@ -194,40 +252,65 @@ export interface ModalConfig {
194
252
  export interface ComposerConfig {
195
253
  /**
196
254
  * The placeholder text for the composer input.
255
+ * @default 'Send a message...'
197
256
  */
198
- placeholder: string;
257
+ placeholder?: string;
199
258
  /**
200
- * Whether to enable attachments in the composer.
201
- *
202
- * NOTE: Not yet implemented
259
+ * Configuration for file attachments in the composer.
260
+ * Set to `false` to disable attachments entirely.
261
+ * Set to `true` for default attachment behavior.
262
+ * Or provide an object for fine-grained control.
263
+ * @default true
264
+ */
265
+ attachments?: boolean | AttachmentsConfig;
266
+ }
267
+ /**
268
+ * AttachmentsConfig provides fine-grained control over file attachments.
269
+ * Inspired by OpenAI ChatKit's attachment options.
270
+ *
271
+ * Note: not yet implemented on the Gram side.
272
+ */
273
+ export interface AttachmentsConfig {
274
+ /**
275
+ * Accepted file types. Can be MIME types or file extensions.
276
+ * @example ['image/*', '.pdf', '.docx']
277
+ */
278
+ accept?: string[];
279
+ /**
280
+ * Maximum number of files that can be attached at once.
281
+ * @default 10
282
+ */
283
+ maxCount?: number;
284
+ /**
285
+ * Maximum file size in bytes.
286
+ * @default 104857600 (100MB)
287
+ */
288
+ maxSize?: number;
289
+ }
290
+ export interface SidecarConfig {
291
+ /**
292
+ * The title displayed in the sidecar header.
293
+ * @default 'Chat'
294
+ */
295
+ title?: string;
296
+ /**
297
+ * The width of the sidecar panel.
298
+ * @default '400px'
299
+ */
300
+ width?: string | number | `${number}%`;
301
+ /**
302
+ * The width of the sidecar panel when expanded.
303
+ * @default '800px'
203
304
  */
204
- attachments: boolean;
305
+ expandedWidth?: string | number | `${number}%`;
205
306
  }
206
307
  export type ElementsContextType = {
207
308
  config: ElementsConfig;
208
309
  setModel: (model: Model) => void;
209
310
  model: Model;
210
311
  isExpanded: boolean;
211
- setIsExpanded: (isExpanded: boolean) => void;
312
+ setIsExpanded: Dispatch<SetStateAction<boolean>>;
212
313
  isOpen: boolean;
213
314
  setIsOpen: (isOpen: boolean) => void;
214
315
  };
215
- declare const ContentSchema: z.ZodUnion<readonly [z.ZodObject<{
216
- type: z.ZodLiteral<"text">;
217
- text: z.ZodString;
218
- }, z.core.$strip>, z.ZodObject<{
219
- type: z.ZodLiteral<"image">;
220
- data: z.ZodString;
221
- }, z.core.$strip>]>;
222
- export type ToolCallResultContent = z.infer<typeof ContentSchema>;
223
- export declare const ToolCallResultSchema: z.ZodUnion<[z.ZodObject<{
224
- content: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
225
- type: z.ZodLiteral<"text">;
226
- text: z.ZodString;
227
- }, z.core.$strip>, z.ZodObject<{
228
- type: z.ZodLiteral<"image">;
229
- data: z.ZodString;
230
- }, z.core.$strip>]>>;
231
- }, z.core.$strip>, z.ZodUndefined]>;
232
- export type ToolCallResult = z.infer<typeof ToolCallResultSchema>;
233
316
  export {};
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ declare const ContentSchema: z.ZodUnion<readonly [z.ZodObject<{
3
+ type: z.ZodLiteral<"text">;
4
+ text: z.ZodString;
5
+ }, z.core.$strip>, z.ZodObject<{
6
+ type: z.ZodLiteral<"image">;
7
+ data: z.ZodString;
8
+ }, z.core.$strip>]>;
9
+ export type ToolCallResultContent = z.infer<typeof ContentSchema>;
10
+ export declare const ToolCallResultSchema: z.ZodUnion<[z.ZodObject<{
11
+ content: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
12
+ type: z.ZodLiteral<"text">;
13
+ text: z.ZodString;
14
+ }, z.core.$strip>, z.ZodObject<{
15
+ type: z.ZodLiteral<"image">;
16
+ data: z.ZodString;
17
+ }, z.core.$strip>]>>;
18
+ }, z.core.$strip>, z.ZodUndefined]>;
19
+ export type ToolCallResult = z.infer<typeof ToolCallResultSchema>;
20
+ export {};
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.4",
5
+ "version": "1.10.0",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
8
8
  ".": {