@gram-ai/elements 1.11.0 → 1.13.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.
@@ -3,61 +3,70 @@
3
3
  */
4
4
  declare const densityClasses: {
5
5
  readonly compact: {
6
- readonly 'p-sm': "p-1";
6
+ readonly 'p-xs': "p-1";
7
+ readonly 'p-sm': "p-1.5";
7
8
  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";
9
+ readonly 'p-lg': "p-2.5";
10
+ readonly 'p-xl': "p-3";
11
+ readonly 'px-xs': "px-1";
12
+ readonly 'px-sm': "px-1.5";
13
+ readonly 'px-md': "px-2";
14
+ readonly 'px-lg': "px-2.5";
15
+ readonly 'px-xl': "px-3";
16
+ readonly 'py-xs': "py-1";
17
+ readonly 'py-sm': "py-1.5";
18
+ readonly 'py-md': "py-2";
19
+ readonly 'py-lg': "py-2.5";
17
20
  readonly 'py-xl': "py-3";
18
21
  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 'gap-md': "gap-1.5";
23
+ readonly 'gap-lg': "gap-2";
24
+ readonly 'gap-xl': "gap-2.5";
22
25
  readonly 'h-header': "h-10";
23
- readonly 'h-input': "min-h-12";
26
+ readonly 'h-input': "min-h-10";
24
27
  readonly 'text-base': "text-sm";
25
28
  readonly 'text-title': "text-xl";
26
29
  readonly 'text-subtitle': "text-sm";
27
30
  };
28
31
  readonly normal: {
32
+ readonly 'p-xs': "p-1";
29
33
  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";
34
+ readonly 'p-md': "p-3";
35
+ readonly 'p-lg': "p-4";
36
+ readonly 'p-xl': "p-6";
37
+ readonly 'px-xs': "px-1";
38
+ readonly 'px-sm': "px-2";
39
+ readonly 'px-md': "px-3";
40
+ readonly 'px-lg': "px-4";
41
+ readonly 'px-xl': "px-6";
42
+ readonly 'py-xs': "py-1";
43
+ readonly 'py-sm': "py-2";
44
+ readonly 'py-md': "py-3";
45
+ readonly 'py-lg': "py-4";
46
+ readonly 'py-xl': "py-6";
47
+ readonly 'gap-sm': "gap-1.5";
42
48
  readonly 'gap-md': "gap-2";
43
49
  readonly 'gap-lg': "gap-3";
44
- readonly 'gap-xl': "gap-5";
50
+ readonly 'gap-xl': "gap-4";
45
51
  readonly 'h-header': "h-12";
46
- readonly 'h-input': "min-h-16";
52
+ readonly 'h-input': "min-h-12";
47
53
  readonly 'text-base': "text-base";
48
54
  readonly 'text-title': "text-2xl";
49
55
  readonly 'text-subtitle': "text-base";
50
56
  };
51
57
  readonly spacious: {
58
+ readonly 'p-xs': "p-2";
52
59
  readonly 'p-sm': "p-3";
53
- readonly 'p-md': "p-6";
54
- readonly 'p-lg': "p-8";
60
+ readonly 'p-md': "p-4";
61
+ readonly 'p-lg': "p-6";
55
62
  readonly 'p-xl': "p-10";
56
- readonly 'px-sm': "px-4";
57
- readonly 'px-md': "px-6";
58
- readonly 'px-lg': "px-8";
63
+ readonly 'px-xs': "px-2";
64
+ readonly 'px-sm': "px-3";
65
+ readonly 'px-md': "px-4";
66
+ readonly 'px-lg': "px-6";
59
67
  readonly 'px-xl': "px-10";
60
- readonly 'py-sm': "py-2";
68
+ readonly 'py-xs': "py-2";
69
+ readonly 'py-sm': "py-3";
61
70
  readonly 'py-md': "py-4";
62
71
  readonly 'py-lg': "py-6";
63
72
  readonly 'py-xl': "py-10";
@@ -66,7 +75,7 @@ declare const densityClasses: {
66
75
  readonly 'gap-lg': "gap-4";
67
76
  readonly 'gap-xl': "gap-6";
68
77
  readonly 'h-header': "h-14";
69
- readonly 'h-input': "min-h-20";
78
+ readonly 'h-input': "min-h-16";
70
79
  readonly 'text-base': "text-lg";
71
80
  readonly 'text-title': "text-3xl";
72
81
  readonly 'text-subtitle': "text-lg";
@@ -77,5 +86,5 @@ type DensityToken = keyof (typeof densityClasses)['normal'];
77
86
  * Hook to get density classes based on theme config
78
87
  * Use: const d = useDensity(); then d('p-md') returns the appropriate padding class
79
88
  */
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";
89
+ export declare const useDensity: () => (token: DensityToken) => "p-1" | "p-1.5" | "p-2" | "p-2.5" | "p-3" | "px-1" | "px-1.5" | "px-2" | "px-2.5" | "px-3" | "py-1" | "py-1.5" | "py-2" | "py-2.5" | "py-3" | "gap-1" | "gap-1.5" | "gap-2" | "gap-2.5" | "h-10" | "min-h-10" | "text-sm" | "text-xl" | "p-4" | "p-6" | "px-4" | "px-6" | "py-4" | "py-6" | "gap-3" | "gap-4" | "h-12" | "min-h-12" | "text-base" | "text-2xl" | "p-10" | "px-10" | "py-10" | "gap-6" | "h-14" | "min-h-16" | "text-lg" | "text-3xl";
81
90
  export {};
@@ -2,6 +2,7 @@ import { Dispatch, SetStateAction } from 'react';
2
2
  interface UseExpandedAPI {
3
3
  expandable: boolean;
4
4
  isExpanded: boolean;
5
+ defaultExpanded: boolean;
5
6
  setIsExpanded: Dispatch<SetStateAction<boolean>>;
6
7
  }
7
8
  export declare const useExpanded: () => UseExpandedAPI;
@@ -0,0 +1 @@
1
+ export declare function humanizeToolName(toolName: string): string;
@@ -1,3 +1,4 @@
1
1
  import { ClassValue } from 'clsx';
2
2
  export declare function cn(...inputs: ClassValue[]): string;
3
3
  export declare function assertNever(value: unknown): never;
4
+ export declare function assert(condition: boolean, message: string): asserts condition;
@@ -1,6 +1,6 @@
1
1
  import { MODELS } from '../lib/models';
2
- import { ToolCallMessagePartComponent } from '@assistant-ui/react';
3
- import { Dispatch, SetStateAction, ReactNode } from 'react';
2
+ import { ImageMessagePartComponent, ReasoningGroupComponent, ReasoningMessagePartComponent, TextMessagePartComponent, ToolCallMessagePartComponent } from '@assistant-ui/react';
3
+ import { ComponentType, Dispatch, PropsWithChildren, SetStateAction, ReactNode } from 'react';
4
4
  import { Plugin } from './plugins';
5
5
  export interface ElementsProviderProps {
6
6
  /**
@@ -20,7 +20,13 @@ export interface ElementsConfig {
20
20
  * The system prompt to use for the Elements library.
21
21
  */
22
22
  systemPrompt?: string;
23
+ /**
24
+ * Any plugins to use for the Elements library.
25
+ *
26
+ * @default import { recommended } from '@gram-ai/elements/plugins'
27
+ */
23
28
  plugins?: Plugin[];
29
+ components?: ComponentOverrides;
24
30
  /**
25
31
  * The project slug to use for the Elements library.
26
32
  */
@@ -155,6 +161,57 @@ export interface ThemeConfig {
155
161
  */
156
162
  radius?: Radius;
157
163
  }
164
+ export interface ComponentOverrides {
165
+ /**
166
+ * The component to use for the composer (the input area where users type messages)
167
+ */
168
+ Composer?: ComponentType;
169
+ /**
170
+ * The component to use for the user message.
171
+ */
172
+ UserMessage?: ComponentType;
173
+ /**
174
+ * The component to use for the edit composer (inline message editor)
175
+ */
176
+ EditComposer?: ComponentType;
177
+ /**
178
+ * The component to use for the assistant message (messages generated by the LLM).
179
+ *
180
+ * Note: if you override this, the Text component will not be used.
181
+ */
182
+ AssistantMessage?: ComponentType;
183
+ /**
184
+ * The component to use for the thread welcome.
185
+ */
186
+ ThreadWelcome?: ComponentType;
187
+ /**
188
+ * The component to use for the text message.
189
+ */
190
+ Text?: TextMessagePartComponent;
191
+ /**
192
+ * The component to use for the image message.
193
+ */
194
+ Image?: ImageMessagePartComponent;
195
+ /**
196
+ * The component to use for the tool fallback (default UI shown when a tool returns a result).
197
+ */
198
+ ToolFallback?: ToolCallMessagePartComponent;
199
+ /**
200
+ * The component to use for the reasoning message.
201
+ */
202
+ Reasoning?: ReasoningMessagePartComponent;
203
+ /**
204
+ * The component to use for the reasoning group.
205
+ */
206
+ ReasoningGroup?: ReasoningGroupComponent;
207
+ /**
208
+ * The component to use for the tool group (a group of tool calls returned by the LLM in a single message).
209
+ */
210
+ ToolGroup?: ComponentType<PropsWithChildren<{
211
+ startIndex: number;
212
+ endIndex: number;
213
+ }>>;
214
+ }
158
215
  /**
159
216
  * ToolsConfig is used to configure tool support in the Elements library.
160
217
  * At the moment, you can override the default React components used by
@@ -170,6 +227,11 @@ export interface ThemeConfig {
170
227
  * }
171
228
  */
172
229
  export interface ToolsConfig {
230
+ /**
231
+ * Whether individual tool calls within a group should be expanded by default.
232
+ * @default false
233
+ */
234
+ expandToolGroupsByDefault?: boolean;
173
235
  /**
174
236
  * `components` can be used to override the default components used by the
175
237
  * Elements library for a given tool result.
@@ -206,13 +268,34 @@ export interface Suggestion {
206
268
  label: string;
207
269
  action: string;
208
270
  }
209
- type ModalDimension = {
210
- width: number | `${number}%`;
211
- height: number | `${number}%`;
212
- maxHeight?: number | `${number}%`;
213
- };
271
+ interface ExpandableDimensions {
272
+ default: {
273
+ width: number | string;
274
+ height: number | string;
275
+ maxHeight?: number | string;
276
+ };
277
+ expanded?: {
278
+ width: number | string;
279
+ height: number | string;
280
+ };
281
+ }
282
+ interface ExpandedConfig {
283
+ /**
284
+ * Whether the modal can be expanded to full screen.
285
+ */
286
+ expandable?: boolean;
287
+ /**
288
+ * Whether the modal should be expanded by default.
289
+ * @default false
290
+ */
291
+ defaultExpanded?: boolean;
292
+ /**
293
+ * The dimensions for the modal window.
294
+ */
295
+ dimensions?: ExpandableDimensions;
296
+ }
214
297
  export type ModalTriggerPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
215
- export interface ModalConfig {
298
+ export interface ModalConfig extends ExpandedConfig {
216
299
  /**
217
300
  * Whether to open the modal window by default.
218
301
  */
@@ -233,23 +316,6 @@ export interface ModalConfig {
233
316
  * Receives the current state of the modal window.
234
317
  */
235
318
  icon?: (state: 'open' | 'closed' | undefined) => ReactNode;
236
- /**
237
- * Whether the modal can be expanded to full screen.
238
- */
239
- expandable?: boolean;
240
- /**
241
- * The dimensions for the modal window.
242
- */
243
- dimensions?: {
244
- /**
245
- * The default dimensions for the modal window.
246
- */
247
- default: ModalDimension;
248
- /**
249
- * The expanded dimensions for the modal window.
250
- */
251
- expanded?: Pick<ModalDimension, 'width' | 'height'>;
252
- };
253
319
  }
254
320
  export interface ComposerConfig {
255
321
  /**
@@ -289,22 +355,12 @@ export interface AttachmentsConfig {
289
355
  */
290
356
  maxSize?: number;
291
357
  }
292
- export interface SidecarConfig {
358
+ export interface SidecarConfig extends ExpandedConfig {
293
359
  /**
294
360
  * The title displayed in the sidecar header.
295
361
  * @default 'Chat'
296
362
  */
297
363
  title?: string;
298
- /**
299
- * The width of the sidecar panel.
300
- * @default '400px'
301
- */
302
- width?: string | number | `${number}%`;
303
- /**
304
- * The width of the sidecar panel when expanded.
305
- * @default '800px'
306
- */
307
- expandedWidth?: string | number | `${number}%`;
308
364
  }
309
365
  export type ElementsContextType = {
310
366
  config: ElementsConfig;
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.11.0",
5
+ "version": "1.13.0",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
8
8
  ".": {