@elabs-ai/components-ai 4.0.0 → 4.1.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.
Files changed (128) hide show
  1. package/README.md +61 -11
  2. package/dist/{_audio-player-media-chrome-KA5DY54G.js → _audio-player-media-chrome-T3XVXWRZ.js} +8 -4
  3. package/dist/_audio-player-media-chrome-T3XVXWRZ.js.map +1 -0
  4. package/dist/{_flow-boundary-D63PJ65S.js → _flow-boundary-SHNWLQG5.js} +32 -43
  5. package/dist/_flow-boundary-SHNWLQG5.js.map +1 -0
  6. package/dist/{_persona-rive-RFR2EUWP.js → _persona-rive-JEG44YHX.js} +9 -5
  7. package/dist/_persona-rive-JEG44YHX.js.map +1 -0
  8. package/dist/index.d.ts +1109 -202
  9. package/dist/index.js +4867 -2878
  10. package/dist/index.js.map +1 -1
  11. package/package.json +31 -16
  12. package/src/_audio-player-media-chrome.tsx +102 -15
  13. package/src/_flow-boundary.tsx +68 -49
  14. package/src/_lazy-boundary-conformance.ts +38 -0
  15. package/src/_lazy-engine-boundary.tsx +61 -0
  16. package/src/_lazy-mermaid-absent.test.ts +53 -0
  17. package/src/_lazy-mermaid.test.ts +15 -0
  18. package/src/_lazy-mermaid.ts +24 -1
  19. package/src/_mermaid-error-panel.test.tsx +50 -0
  20. package/src/_mermaid-error-panel.tsx +66 -0
  21. package/src/_persona-rive.tsx +62 -10
  22. package/src/_streamdown-i18n.ts +21 -1
  23. package/src/_streamdown-safety.ts +170 -0
  24. package/src/agent-event.stories.tsx +97 -0
  25. package/src/agent-event.test.tsx +145 -0
  26. package/src/agent-event.tsx +187 -0
  27. package/src/agent-timeline.stories.tsx +9 -1
  28. package/src/agent.test.tsx +47 -0
  29. package/src/agent.tsx +28 -14
  30. package/src/agentic-workspace.stories.tsx +27 -20
  31. package/src/artifact.tsx +15 -12
  32. package/src/audio-player.test.tsx +78 -0
  33. package/src/audio-player.tsx +243 -56
  34. package/src/audio-visualizer.stories.tsx +126 -0
  35. package/src/audio-visualizer.test.tsx +438 -0
  36. package/src/audio-visualizer.tsx +367 -0
  37. package/src/canvas.stories.tsx +150 -1
  38. package/src/chat-shell.stories.tsx +18 -3
  39. package/src/chat.stories.tsx +16 -2
  40. package/src/code-block.stories.tsx +9 -1
  41. package/src/composer.stories.tsx +372 -9
  42. package/src/composer.test.tsx +357 -6
  43. package/src/composer.tsx +217 -35
  44. package/src/confirmation.stories.tsx +72 -1
  45. package/src/confirmation.test.tsx +216 -2
  46. package/src/confirmation.tsx +263 -3
  47. package/src/context-panel.stories.tsx +9 -1
  48. package/src/context-panel.tsx +2 -1
  49. package/src/conversation.stories.tsx +63 -2
  50. package/src/conversation.test.tsx +13 -0
  51. package/src/conversation.tsx +20 -2
  52. package/src/diff-view.stories.tsx +196 -0
  53. package/src/diff-view.test.tsx +188 -0
  54. package/src/diff-view.tsx +642 -0
  55. package/src/gallery.tsx +4 -2
  56. package/src/index.ts +14 -4
  57. package/src/jsx-preview.stories.tsx +2 -2
  58. package/src/markdown-view.stories.tsx +92 -1
  59. package/src/markdown-view.test.tsx +232 -1
  60. package/src/markdown-view.tsx +150 -6
  61. package/src/message-compare.stories.tsx +175 -0
  62. package/src/message-compare.test.tsx +207 -0
  63. package/src/message-compare.tsx +453 -0
  64. package/src/message-form.stories.tsx +29 -1
  65. package/src/message.stories.tsx +9 -1
  66. package/src/message.test.tsx +176 -0
  67. package/src/message.tsx +90 -4
  68. package/src/microcopy.test.tsx +40 -0
  69. package/src/{model-selector.stories.tsx → model-provider-logo.stories.tsx} +17 -8
  70. package/src/{model-selector.test.tsx → model-provider-logo.test.tsx} +10 -10
  71. package/src/model-provider-logo.tsx +149 -0
  72. package/src/permission-mode-select.stories.tsx +82 -0
  73. package/src/permission-mode-select.test.tsx +100 -0
  74. package/src/permission-mode-select.tsx +137 -0
  75. package/src/persona-missing-peer.test.tsx +54 -0
  76. package/src/persona.tsx +68 -22
  77. package/src/plan.stories.tsx +166 -0
  78. package/src/plan.test.tsx +267 -0
  79. package/src/plan.tsx +182 -20
  80. package/src/prompt-input-effort.stories.tsx +123 -0
  81. package/src/prompt-input-effort.test.tsx +83 -0
  82. package/src/prompt-input-effort.tsx +136 -0
  83. package/src/prompt-input-mode.stories.tsx +108 -0
  84. package/src/prompt-input-mode.test.tsx +99 -0
  85. package/src/prompt-input-mode.tsx +169 -0
  86. package/src/prompt-input-slash.stories.tsx +211 -0
  87. package/src/prompt-input-slash.test.tsx +262 -0
  88. package/src/prompt-input-slash.tsx +541 -0
  89. package/src/prompt-input.stories.tsx +2 -2
  90. package/src/reasoning.tsx +27 -13
  91. package/src/sandbox.stories.tsx +9 -1
  92. package/src/schema-display.tsx +5 -2
  93. package/src/selection-toolbar.stories.tsx +9 -1
  94. package/src/session-header.stories.tsx +128 -0
  95. package/src/session-header.test.tsx +138 -0
  96. package/src/session-header.tsx +243 -0
  97. package/src/session-status-bar.stories.tsx +73 -0
  98. package/src/session-status-bar.test.tsx +94 -0
  99. package/src/session-status-bar.tsx +165 -0
  100. package/src/snippet.stories.tsx +9 -1
  101. package/src/stack-trace.tsx +6 -2
  102. package/src/streamdown-i18n.test.tsx +1 -1
  103. package/src/task.stories.tsx +13 -3
  104. package/src/templates-ai-assistant.stories.tsx +21 -1
  105. package/src/token-usage.stories.tsx +24 -0
  106. package/src/token-usage.test.tsx +92 -0
  107. package/src/{context.tsx → token-usage.tsx} +67 -53
  108. package/src/tool-result-card.stories.tsx +9 -1
  109. package/src/tool.stories.tsx +13 -3
  110. package/src/tool.tsx +15 -8
  111. package/src/turn-status.stories.tsx +124 -0
  112. package/src/turn-status.test.tsx +74 -0
  113. package/src/turn-status.tsx +174 -0
  114. package/src/use-audio-level.ts +104 -0
  115. package/src/web-preview.tsx +8 -3
  116. package/dist/_audio-player-media-chrome-KA5DY54G.js.map +0 -1
  117. package/dist/_flow-boundary-D63PJ65S.js.map +0 -1
  118. package/dist/_interactive-terminal-xterm-ATJ5EW3G.js +0 -11
  119. package/dist/_interactive-terminal-xterm-ATJ5EW3G.js.map +0 -1
  120. package/dist/_persona-rive-RFR2EUWP.js.map +0 -1
  121. package/src/_interactive-terminal-xterm.ts +0 -32
  122. package/src/blocks-ai-composer.stories.tsx +0 -83
  123. package/src/context.stories.tsx +0 -16
  124. package/src/interactive-terminal.stories.tsx +0 -165
  125. package/src/interactive-terminal.test.tsx +0 -448
  126. package/src/interactive-terminal.tsx +0 -444
  127. package/src/model-selector.tsx +0 -225
  128. package/src/terminal.tsx +0 -244
package/src/terminal.tsx DELETED
@@ -1,244 +0,0 @@
1
- "use client";
2
-
3
- import { Button } from "@elabs-ai/components-ui";
4
- import { cn } from "@elabs-ai/components-ui/lib/cn";
5
- import Ansi from "ansi-to-react";
6
- import { CheckIcon, CopyIcon, TerminalIcon, Trash2Icon } from "lucide-react";
7
- import type { ComponentProps, HTMLAttributes } from "react";
8
- import {
9
- createContext,
10
- useCallback,
11
- useContext,
12
- useEffect,
13
- useMemo,
14
- useRef,
15
- useState,
16
- } from "react";
17
-
18
- interface TerminalContextType {
19
- output: string;
20
- isStreaming: boolean;
21
- autoScroll: boolean;
22
- onClear?: () => void;
23
- }
24
-
25
- const TerminalContext = createContext<TerminalContextType>({
26
- autoScroll: true,
27
- isStreaming: false,
28
- output: "",
29
- });
30
-
31
- export type TerminalHeaderProps = HTMLAttributes<HTMLDivElement>;
32
-
33
- export const TerminalHeader = ({ className, children, ...props }: TerminalHeaderProps) => (
34
- <div
35
- className={cn(
36
- "flex items-center justify-between border-zinc-800 border-b px-4 py-2",
37
- className,
38
- )}
39
- {...props}
40
- >
41
- {children}
42
- </div>
43
- );
44
-
45
- export type TerminalTitleProps = HTMLAttributes<HTMLDivElement>;
46
-
47
- export const TerminalTitle = ({ className, children, ...props }: TerminalTitleProps) => (
48
- <div className={cn("flex items-center gap-2 text-sm text-zinc-400", className)} {...props}>
49
- <TerminalIcon className="size-4" />
50
- {children ?? "Terminal"}
51
- </div>
52
- );
53
-
54
- export type TerminalStatusProps = HTMLAttributes<HTMLDivElement>;
55
-
56
- export const TerminalStatus = ({ className, children, ...props }: TerminalStatusProps) => {
57
- const { isStreaming } = useContext(TerminalContext);
58
-
59
- if (!isStreaming) {
60
- return null;
61
- }
62
-
63
- return (
64
- <div className={cn("flex items-center gap-2 text-xs text-zinc-400", className)} {...props}>
65
- {children}
66
- </div>
67
- );
68
- };
69
-
70
- export type TerminalActionsProps = HTMLAttributes<HTMLDivElement>;
71
-
72
- export const TerminalActions = ({ className, children, ...props }: TerminalActionsProps) => (
73
- <div className={cn("flex items-center gap-1", className)} {...props}>
74
- {children}
75
- </div>
76
- );
77
-
78
- export type TerminalCopyButtonProps = ComponentProps<typeof Button> & {
79
- onCopy?: () => void;
80
- onError?: (error: Error) => void;
81
- timeout?: number;
82
- };
83
-
84
- export const TerminalCopyButton = ({
85
- onCopy,
86
- onError,
87
- timeout = 2000,
88
- children,
89
- className,
90
- ...props
91
- }: TerminalCopyButtonProps) => {
92
- const [isCopied, setIsCopied] = useState(false);
93
- const timeoutRef = useRef<number>(0);
94
- const { output } = useContext(TerminalContext);
95
-
96
- const copyToClipboard = useCallback(async () => {
97
- if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
98
- onError?.(new Error("Clipboard API not available"));
99
- return;
100
- }
101
-
102
- try {
103
- await navigator.clipboard.writeText(output);
104
- setIsCopied(true);
105
- onCopy?.();
106
- timeoutRef.current = window.setTimeout(() => setIsCopied(false), timeout);
107
- } catch (error) {
108
- onError?.(error as Error);
109
- }
110
- }, [output, onCopy, onError, timeout]);
111
-
112
- useEffect(
113
- () => () => {
114
- window.clearTimeout(timeoutRef.current);
115
- },
116
- [],
117
- );
118
-
119
- const Icon = isCopied ? CheckIcon : CopyIcon;
120
-
121
- return (
122
- <Button
123
- className={cn(
124
- "size-7 shrink-0 text-zinc-400 hover:bg-zinc-800 hover:text-zinc-100",
125
- className,
126
- )}
127
- onClick={copyToClipboard}
128
- size="icon"
129
- variant="ghost"
130
- {...props}
131
- >
132
- {children ?? <Icon size={14} />}
133
- </Button>
134
- );
135
- };
136
-
137
- export type TerminalClearButtonProps = ComponentProps<typeof Button>;
138
-
139
- export const TerminalClearButton = ({
140
- children,
141
- className,
142
- ...props
143
- }: TerminalClearButtonProps) => {
144
- const { onClear } = useContext(TerminalContext);
145
-
146
- if (!onClear) {
147
- return null;
148
- }
149
-
150
- return (
151
- <Button
152
- className={cn(
153
- "size-7 shrink-0 text-zinc-400 hover:bg-zinc-800 hover:text-zinc-100",
154
- className,
155
- )}
156
- onClick={onClear}
157
- size="icon"
158
- variant="ghost"
159
- {...props}
160
- >
161
- {children ?? <Trash2Icon size={14} />}
162
- </Button>
163
- );
164
- };
165
-
166
- export type TerminalContentProps = HTMLAttributes<HTMLDivElement>;
167
-
168
- export const TerminalContent = ({ className, children, ...props }: TerminalContentProps) => {
169
- const { output, isStreaming, autoScroll } = useContext(TerminalContext);
170
- const containerRef = useRef<HTMLDivElement>(null);
171
-
172
- useEffect(() => {
173
- if (autoScroll && containerRef.current) {
174
- containerRef.current.scrollTop = containerRef.current.scrollHeight;
175
- }
176
- }, [output, autoScroll]);
177
-
178
- return (
179
- <div
180
- className={cn("max-h-96 overflow-auto p-4 font-mono text-sm leading-relaxed", className)}
181
- ref={containerRef}
182
- {...props}
183
- >
184
- {children ?? (
185
- <pre className="whitespace-pre-wrap break-words">
186
- <Ansi>{output}</Ansi>
187
- {isStreaming && (
188
- <span className="ml-0.5 inline-block h-4 w-2 animate-pulse bg-zinc-100" />
189
- )}
190
- </pre>
191
- )}
192
- </div>
193
- );
194
- };
195
-
196
- export type TerminalProps = HTMLAttributes<HTMLDivElement> & {
197
- output: string;
198
- isStreaming?: boolean;
199
- autoScroll?: boolean;
200
- onClear?: () => void;
201
- };
202
-
203
- export const Terminal = ({
204
- output,
205
- isStreaming = false,
206
- autoScroll = true,
207
- onClear,
208
- className,
209
- children,
210
- ...props
211
- }: TerminalProps) => {
212
- const contextValue = useMemo(
213
- () => ({ autoScroll, isStreaming, onClear, output }),
214
- [autoScroll, isStreaming, onClear, output],
215
- );
216
-
217
- return (
218
- <TerminalContext.Provider value={contextValue}>
219
- <div
220
- className={cn(
221
- "flex flex-col overflow-hidden rounded-lg border bg-zinc-950 text-zinc-100",
222
- className,
223
- )}
224
- {...props}
225
- >
226
- {children ?? (
227
- <>
228
- <TerminalHeader>
229
- <TerminalTitle />
230
- <div className="flex items-center gap-1">
231
- <TerminalStatus />
232
- <TerminalActions>
233
- <TerminalCopyButton />
234
- {onClear && <TerminalClearButton />}
235
- </TerminalActions>
236
- </div>
237
- </TerminalHeader>
238
- <TerminalContent />
239
- </>
240
- )}
241
- </div>
242
- </TerminalContext.Provider>
243
- );
244
- };