@mcp-b/react-components 0.13.0 → 0.14.1
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/dist/{AgentChat-Br6tKEl8.d.ts → AgentChat-Cgb1xuT7.d.ts} +8 -1
- package/dist/{PromptInput-p5KmOmt1.d.ts → PromptInput-ClNqBiIw.d.ts} +11 -0
- package/dist/{ThinkChatActivity-Cuk28Js_.d.ts → ThinkChatActivity-m9orbdeI.d.ts} +1 -1
- package/dist/components/AgentChat.d.ts +1 -1
- package/dist/components/AgentChat.js +8 -3
- package/dist/components/McpServerPicker.d.ts +1 -1
- package/dist/components/McpServerPicker.js +6 -0
- package/dist/components/PromptInput.d.ts +1 -1
- package/dist/components/PromptInput.js +215 -48
- package/dist/components/ThinkChat.d.ts +7 -2
- package/dist/components/ThinkChatActivity.d.ts +1 -1
- package/dist/styles/activity.css +6 -0
- package/dist/styles/agent-chat.css +7 -1
- package/dist/styles/message-scroller.css +1 -1
- package/dist/styles/message.css +2 -0
- package/dist/styles/prompt-input.css +90 -0
- package/dist/styles/streamdown.css +10 -0
- package/dist/styles/workspace-explorer.css +1 -0
- package/dist/utils/codex-model-catalog.d.ts +4 -4
- package/package.json +2 -2
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { tt as PromptInputMessage } from "./PromptInput-
|
|
1
|
+
import { W as PromptInputDictationProps, tt as PromptInputMessage } from "./PromptInput-ClNqBiIw.js";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { ChatAddToolApproveResponseFunction, ChatStatus, UIMessage } from "ai";
|
|
4
4
|
import { PendingApproval, Think } from "@cloudflare/think";
|
|
5
5
|
import { AgentStub } from "agents/client";
|
|
6
|
+
import { UseVoiceInputReturn } from "@cloudflare/voice/react";
|
|
6
7
|
|
|
7
8
|
//#region src/components/AgentChat.d.ts
|
|
8
9
|
type AgentChatPart<MessageT extends UIMessage = UIMessage> = MessageT["parts"][number];
|
|
@@ -85,6 +86,10 @@ interface AgentChatProps<MessageT extends UIMessage = UIMessage> {
|
|
|
85
86
|
emptyState?: React.ReactNode;
|
|
86
87
|
/** Extra controls rendered in the composer toolbar. */
|
|
87
88
|
composerTools?: React.ReactNode;
|
|
89
|
+
/** Whole upstream voice-input hook result used by the built-in dictation recorder. */
|
|
90
|
+
voiceInput?: UseVoiceInputReturn;
|
|
91
|
+
/** Host prerequisite run before the built-in recorder calls `voiceInput.start()`. */
|
|
92
|
+
beforeVoiceStart?: PromptInputDictationProps["beforeStart"];
|
|
88
93
|
/**
|
|
89
94
|
* Rendered in the prompt-composer header before attachments and the text
|
|
90
95
|
* field. Use it to compose a compact Activity, task state, or app-specific
|
|
@@ -175,6 +180,8 @@ declare function AgentChat<MessageT extends UIMessage = UIMessage>({
|
|
|
175
180
|
emptyState,
|
|
176
181
|
composerHeader,
|
|
177
182
|
composerTools,
|
|
183
|
+
voiceInput,
|
|
184
|
+
beforeVoiceStart,
|
|
178
185
|
composerAddMenuItems,
|
|
179
186
|
notice,
|
|
180
187
|
onRegenerate,
|
|
@@ -235,6 +235,16 @@ declare function PromptInputButton({
|
|
|
235
235
|
interface PromptInputDictationProps extends Omit<PromptInputButtonProps, "children" | "onClick" | "tooltip"> {
|
|
236
236
|
/** The whole upstream `useVoiceInput` result; authentication and transport stay in the host. */
|
|
237
237
|
voice: UseVoiceInputReturn;
|
|
238
|
+
/**
|
|
239
|
+
* Runs immediately before the unchanged upstream `voice.start()` call.
|
|
240
|
+
* Use this for host-specific prerequisites, such as opening an extension tab
|
|
241
|
+
* that can present Chrome's microphone permission prompt. Reject to prevent
|
|
242
|
+
* `voice.start()` and surface the error in the composer.
|
|
243
|
+
*
|
|
244
|
+
* @see https://github.com/cloudflare/agents/blob/main/examples/voice-input/src/client.tsx
|
|
245
|
+
* @see https://developer.chrome.com/docs/extensions/reference/api/offscreen#type-Reason
|
|
246
|
+
*/
|
|
247
|
+
beforeStart?: (voice: UseVoiceInputReturn) => void | Promise<void>;
|
|
238
248
|
}
|
|
239
249
|
/**
|
|
240
250
|
* Voice-dictation control for PromptInput. Final upstream transcripts are
|
|
@@ -242,6 +252,7 @@ interface PromptInputDictationProps extends Omit<PromptInputButtonProps, "childr
|
|
|
242
252
|
*/
|
|
243
253
|
declare function PromptInputDictation({
|
|
244
254
|
voice,
|
|
255
|
+
beforeStart,
|
|
245
256
|
className,
|
|
246
257
|
disabled,
|
|
247
258
|
ref,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as AgentChatRenderPartContext, r as AgentChatProps } from "./AgentChat-
|
|
1
|
+
import { a as AgentChatRenderPartContext, r as AgentChatProps } from "./AgentChat-Cgb1xuT7.js";
|
|
2
2
|
import { s as ThinkChatPart } from "./ThinkChatToolParts-Cv4o7j6F.js";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { DynamicToolUIPart, ToolUIPart, UIMessage } from "ai";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as AgentChatRenderPartContext, i as AgentChatRenderMessageContext, n as AgentChatPart, r as AgentChatProps, t as AgentChat } from "../AgentChat-
|
|
1
|
+
import { a as AgentChatRenderPartContext, i as AgentChatRenderMessageContext, n as AgentChatPart, r as AgentChatProps, t as AgentChat } from "../AgentChat-Cgb1xuT7.js";
|
|
2
2
|
export { AgentChat, AgentChatPart, AgentChatProps, AgentChatRenderMessageContext, AgentChatRenderPartContext };
|
|
@@ -7,7 +7,7 @@ import { MessageScroller, MessageScrollerButton, MessageScrollerContent, Message
|
|
|
7
7
|
import { ConversationEmptyState } from "./Conversation.js";
|
|
8
8
|
import { Message, MessageAction, MessageActions, MessageAttachment, MessageContent, MessageResponse } from "./Message.js";
|
|
9
9
|
import { Marker, MarkerContent } from "./Marker.js";
|
|
10
|
-
import { PromptInput, PromptInputActionAddAttachments, PromptInputActionMenu, PromptInputActionMenuContent, PromptInputActionMenuTrigger, PromptInputApproval, PromptInputAttachments, PromptInputBody, PromptInputButton, PromptInputFooter, PromptInputHeader, PromptInputPermissionSelector, PromptInputSubmit, PromptInputTextarea, PromptInputTools, getApprovalRequestId, getApprovalStateKey, getPendingToolApprovals, usePromptInputAttachments } from "./PromptInput.js";
|
|
10
|
+
import { PromptInput, PromptInputActionAddAttachments, PromptInputActionMenu, PromptInputActionMenuContent, PromptInputActionMenuTrigger, PromptInputApproval, PromptInputAttachments, PromptInputBody, PromptInputButton, PromptInputDictation, PromptInputFooter, PromptInputHeader, PromptInputPermissionSelector, PromptInputSubmit, PromptInputTextarea, PromptInputTools, getApprovalRequestId, getApprovalStateKey, getPendingToolApprovals, usePromptInputAttachments } from "./PromptInput.js";
|
|
11
11
|
import { Reasoning, ReasoningContent, ReasoningTrigger } from "./Reasoning.js";
|
|
12
12
|
import { Source, Sources, SourcesContent, SourcesTrigger } from "./Sources.js";
|
|
13
13
|
import { t as CopyButton } from "../copy-button-DUMLYdsk.js";
|
|
@@ -310,7 +310,7 @@ function renderDefaultPart(part) {
|
|
|
310
310
|
* transport. Product code that talks to a Cloudflare Think agent should render
|
|
311
311
|
* `ThinkChat`; use this directly only for plain AI SDK or read-only messages.
|
|
312
312
|
*/
|
|
313
|
-
function AgentChat({ className, messages, status = "ready", onSubmit, onStop, placeholder = "Ask anything...", disabled, emptyState, composerHeader, composerTools, composerAddMenuItems, notice, onRegenerate, onEditAndResend, onApprovalResponse, thinkStub, onExecutionSettled, pendingApprovals: durableApprovals = EMPTY_PENDING_APPROVALS, contextWindow, renderPart, renderMessageAfter, ref }) {
|
|
313
|
+
function AgentChat({ className, messages, status = "ready", onSubmit, onStop, placeholder = "Ask anything...", disabled, emptyState, composerHeader, composerTools, voiceInput, beforeVoiceStart, composerAddMenuItems, notice, onRegenerate, onEditAndResend, onApprovalResponse, thinkStub, onExecutionSettled, pendingApprovals: durableApprovals = EMPTY_PENDING_APPROVALS, contextWindow, renderPart, renderMessageAfter, ref }) {
|
|
314
314
|
const [copyAnnouncement, setCopyAnnouncement] = React.useState("");
|
|
315
315
|
const copyAnnouncementTimer = React.useRef(null);
|
|
316
316
|
const announceCopyStatus = React.useCallback((message) => {
|
|
@@ -551,7 +551,12 @@ function AgentChat({ className, messages, status = "ready", onSubmit, onStop, pl
|
|
|
551
551
|
value: permissionMode,
|
|
552
552
|
onValueChange: setPermissionMode
|
|
553
553
|
}) : null,
|
|
554
|
-
composerTools
|
|
554
|
+
composerTools,
|
|
555
|
+
voiceInput ? /* @__PURE__ */ jsx(PromptInputDictation, {
|
|
556
|
+
voice: voiceInput,
|
|
557
|
+
beforeStart: beforeVoiceStart,
|
|
558
|
+
disabled
|
|
559
|
+
}) : null
|
|
555
560
|
] }), /* @__PURE__ */ jsxs("div", {
|
|
556
561
|
className: "prompt-input__footer-end",
|
|
557
562
|
children: [contextWindow ? /* @__PURE__ */ jsxs(Context, {
|
|
@@ -16,7 +16,7 @@ interface McpServerPickerProps {
|
|
|
16
16
|
onRetry?: McpServerConnectionAction;
|
|
17
17
|
/** Called when a ready/connected server should refresh discovery through an app-owned Agent RPC. */
|
|
18
18
|
onRefresh?: McpServerConnectionAction;
|
|
19
|
-
/** Called when
|
|
19
|
+
/** Called when an authenticating or connected server should be removed or disconnected. */
|
|
20
20
|
onDisconnect?: McpServerConnectionAction;
|
|
21
21
|
/** Offset from the plus trigger to the menu, useful for prompt composers. */
|
|
22
22
|
sideOffset?: number;
|
|
@@ -120,6 +120,12 @@ function McpServerPickerRow({ server, mcp, onConnect, onAuthorize, onDisconnect,
|
|
|
120
120
|
label: pending("authorize") ? `Opening ${server.name}` : `Authorize ${server.name}`,
|
|
121
121
|
onClick: () => onAuthorize(connectedServerId, connectedServer)
|
|
122
122
|
}) : null,
|
|
123
|
+
connectedServer?.state === "authenticating" && connectedServerId && onDisconnect ? /* @__PURE__ */ jsx(McpServerActionItem, {
|
|
124
|
+
disabled: pending("disconnect"),
|
|
125
|
+
icon: /* @__PURE__ */ jsx(MinusIcon, {}),
|
|
126
|
+
label: pending("disconnect") ? `Cancelling ${server.name} authentication` : `Cancel ${server.name} authentication`,
|
|
127
|
+
onClick: () => onDisconnect(connectedServerId, connectedServer)
|
|
128
|
+
}) : null,
|
|
123
129
|
connectedServer?.state === "failed" && connectedServerId && onRetry ? /* @__PURE__ */ jsx(McpServerActionItem, {
|
|
124
130
|
disabled: pending("retry"),
|
|
125
131
|
icon: /* @__PURE__ */ jsx(RefreshIcon, {}),
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as PromptInputHoverCardTrigger, A as PromptInputCommandEmptyProps, At as getPendingToolApprovals, B as PromptInputCommandSeparator, C as PromptInputBody, Ct as PromptInputTools, D as PromptInputButtonTooltip, Dt as TooltipSide, E as PromptInputButtonProps, Et as TextInputContext, F as PromptInputCommandItem, G as PromptInputFooter, H as PromptInputControllerProps, I as PromptInputCommandItemProps, J as PromptInputHeaderProps, K as PromptInputFooterProps, L as PromptInputCommandList, M as PromptInputCommandGroupProps, Mt as usePromptInputController, N as PromptInputCommandInput, Nt as useProviderAttachments, O as PromptInputCommand, Ot as getApprovalRequestId, P as PromptInputCommandInputProps, Q as PromptInputHoverCardProps, R as PromptInputCommandListProps, S as PromptInputAttachmentsProps, St as PromptInputTextareaProps, T as PromptInputButton, Tt as PromptInputTooltipConfig, U as PromptInputDictation, V as PromptInputCommandSeparatorProps, W as PromptInputDictationProps, X as PromptInputHoverCardContent, Y as PromptInputHoverCard, Z as PromptInputHoverCardContentProps, _ as PromptInputApproval, _t as PromptInputTabLabelProps, a as PromptInputActionAddAttachments, at as PromptInputProvider, b as PromptInputAttachmentProps, bt as PromptInputTabsListProps, c as PromptInputActionAddScreenshotProps, ct as PromptInputSelectProps, d as PromptInputActionMenuContentProps, dt as PromptInputTab, et as PromptInputHoverCardTriggerProps, f as PromptInputActionMenuItem, ft as PromptInputTabBody, g as PromptInputActionMenuTriggerProps, gt as PromptInputTabLabel, h as PromptInputActionMenuTrigger, ht as PromptInputTabItemProps, i as PromptInput, it as PromptInputProps, j as PromptInputCommandGroup, jt as usePromptInputAttachments, k as PromptInputCommandEmpty, kt as getApprovalStateKey, l as PromptInputActionMenu, lt as PromptInputSubmit, m as PromptInputActionMenuProps, mt as PromptInputTabItem, n as PendingToolApproval, nt as PromptInputPermissionSelector, o as PromptInputActionAddAttachmentsProps, ot as PromptInputProviderProps, p as PromptInputActionMenuItemProps, pt as PromptInputTabBodyProps, q as PromptInputHeader, r as PermissionMode, rt as PromptInputPermissionSelectorProps, s as PromptInputActionAddScreenshot, st as PromptInputSelect, t as AttachmentsContext, tt as PromptInputMessage, u as PromptInputActionMenuContent, ut as PromptInputSubmitProps, v as PromptInputApprovalProps, vt as PromptInputTabProps, w as PromptInputBodyProps, wt as PromptInputToolsProps, x as PromptInputAttachments, xt as PromptInputTextarea, y as PromptInputAttachment, yt as PromptInputTabsList, z as PromptInputCommandProps } from "../PromptInput-
|
|
1
|
+
import { $ as PromptInputHoverCardTrigger, A as PromptInputCommandEmptyProps, At as getPendingToolApprovals, B as PromptInputCommandSeparator, C as PromptInputBody, Ct as PromptInputTools, D as PromptInputButtonTooltip, Dt as TooltipSide, E as PromptInputButtonProps, Et as TextInputContext, F as PromptInputCommandItem, G as PromptInputFooter, H as PromptInputControllerProps, I as PromptInputCommandItemProps, J as PromptInputHeaderProps, K as PromptInputFooterProps, L as PromptInputCommandList, M as PromptInputCommandGroupProps, Mt as usePromptInputController, N as PromptInputCommandInput, Nt as useProviderAttachments, O as PromptInputCommand, Ot as getApprovalRequestId, P as PromptInputCommandInputProps, Q as PromptInputHoverCardProps, R as PromptInputCommandListProps, S as PromptInputAttachmentsProps, St as PromptInputTextareaProps, T as PromptInputButton, Tt as PromptInputTooltipConfig, U as PromptInputDictation, V as PromptInputCommandSeparatorProps, W as PromptInputDictationProps, X as PromptInputHoverCardContent, Y as PromptInputHoverCard, Z as PromptInputHoverCardContentProps, _ as PromptInputApproval, _t as PromptInputTabLabelProps, a as PromptInputActionAddAttachments, at as PromptInputProvider, b as PromptInputAttachmentProps, bt as PromptInputTabsListProps, c as PromptInputActionAddScreenshotProps, ct as PromptInputSelectProps, d as PromptInputActionMenuContentProps, dt as PromptInputTab, et as PromptInputHoverCardTriggerProps, f as PromptInputActionMenuItem, ft as PromptInputTabBody, g as PromptInputActionMenuTriggerProps, gt as PromptInputTabLabel, h as PromptInputActionMenuTrigger, ht as PromptInputTabItemProps, i as PromptInput, it as PromptInputProps, j as PromptInputCommandGroup, jt as usePromptInputAttachments, k as PromptInputCommandEmpty, kt as getApprovalStateKey, l as PromptInputActionMenu, lt as PromptInputSubmit, m as PromptInputActionMenuProps, mt as PromptInputTabItem, n as PendingToolApproval, nt as PromptInputPermissionSelector, o as PromptInputActionAddAttachmentsProps, ot as PromptInputProviderProps, p as PromptInputActionMenuItemProps, pt as PromptInputTabBodyProps, q as PromptInputHeader, r as PermissionMode, rt as PromptInputPermissionSelectorProps, s as PromptInputActionAddScreenshot, st as PromptInputSelect, t as AttachmentsContext, tt as PromptInputMessage, u as PromptInputActionMenuContent, ut as PromptInputSubmitProps, v as PromptInputApprovalProps, vt as PromptInputTabProps, w as PromptInputBodyProps, wt as PromptInputToolsProps, x as PromptInputAttachments, xt as PromptInputTextarea, y as PromptInputAttachment, yt as PromptInputTabsList, z as PromptInputCommandProps } from "../PromptInput-ClNqBiIw.js";
|
|
2
2
|
export { AttachmentsContext, PendingToolApproval, PermissionMode, PromptInput, PromptInputActionAddAttachments, PromptInputActionAddAttachmentsProps, PromptInputActionAddScreenshot, PromptInputActionAddScreenshotProps, PromptInputActionMenu, PromptInputActionMenuContent, PromptInputActionMenuContentProps, PromptInputActionMenuItem, PromptInputActionMenuItemProps, PromptInputActionMenuProps, PromptInputActionMenuTrigger, PromptInputActionMenuTriggerProps, PromptInputApproval, PromptInputApprovalProps, PromptInputAttachment, PromptInputAttachmentProps, PromptInputAttachments, PromptInputAttachmentsProps, PromptInputBody, PromptInputBodyProps, PromptInputButton, PromptInputButtonProps, PromptInputButtonTooltip, PromptInputCommand, PromptInputCommandEmpty, PromptInputCommandEmptyProps, PromptInputCommandGroup, PromptInputCommandGroupProps, PromptInputCommandInput, PromptInputCommandInputProps, PromptInputCommandItem, PromptInputCommandItemProps, PromptInputCommandList, PromptInputCommandListProps, PromptInputCommandProps, PromptInputCommandSeparator, PromptInputCommandSeparatorProps, PromptInputControllerProps, PromptInputDictation, PromptInputDictationProps, PromptInputFooter, PromptInputFooterProps, PromptInputHeader, PromptInputHeaderProps, PromptInputHoverCard, PromptInputHoverCardContent, PromptInputHoverCardContentProps, PromptInputHoverCardProps, PromptInputHoverCardTrigger, PromptInputHoverCardTriggerProps, PromptInputMessage, PromptInputPermissionSelector, PromptInputPermissionSelectorProps, PromptInputProps, PromptInputProvider, PromptInputProviderProps, PromptInputSelect, PromptInputSelectProps, PromptInputSubmit, PromptInputSubmitProps, PromptInputTab, PromptInputTabBody, PromptInputTabBodyProps, PromptInputTabItem, PromptInputTabItemProps, PromptInputTabLabel, PromptInputTabLabelProps, PromptInputTabProps, PromptInputTabsList, PromptInputTabsListProps, PromptInputTextarea, PromptInputTextareaProps, PromptInputTools, PromptInputToolsProps, PromptInputTooltipConfig, TextInputContext, TooltipSide, getApprovalRequestId, getApprovalStateKey, getPendingToolApprovals, usePromptInputAttachments, usePromptInputController, useProviderAttachments };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as cx } from "../class-names-9UtZwb0J.js";
|
|
2
|
-
import { D as PencilIcon, F as StopIcon, L as WarningIcon, N as SpinnerIcon, P as SquareIcon, S as MicrophoneIcon, T as PaperclipIcon, h as FileIcon, i as ArrowUpIcon, k as PlusIcon, o as ChevronDownIcon, w as MonitorIcon, z as XIcon } from "../icons-Ba9THQKz.js";
|
|
2
|
+
import { D as PencilIcon, F as StopIcon, L as WarningIcon, N as SpinnerIcon, P as SquareIcon, R as WrenchIcon, S as MicrophoneIcon, T as PaperclipIcon, h as FileIcon, i as ArrowUpIcon, k as PlusIcon, o as ChevronDownIcon, w as MonitorIcon, z as XIcon } from "../icons-Ba9THQKz.js";
|
|
3
3
|
import { Button } from "./Button.js";
|
|
4
4
|
import { Tooltip } from "./Tooltip.js";
|
|
5
5
|
import { t as AttachmentPreview } from "../attachment-preview-DIs50Q0h.js";
|
|
@@ -450,6 +450,7 @@ function PromptInputButton({ className, tooltip, variant = "ghost", color = "neu
|
|
|
450
450
|
const resolvedSize = size ?? (React.Children.count(children) > 1 ? "xs" : "icon-xs");
|
|
451
451
|
const tooltipConfig = typeof tooltip === "string" ? { content: tooltip } : tooltip;
|
|
452
452
|
const fallbackLabel = ariaLabel ?? (typeof tooltipConfig?.content === "string" ? tooltipConfig.content : void 0);
|
|
453
|
+
const hasResponsiveLabel = Boolean(tooltipConfig && React.Children.count(children) > 1);
|
|
453
454
|
const button = /* @__PURE__ */ jsx(Button, {
|
|
454
455
|
ref,
|
|
455
456
|
type: "button",
|
|
@@ -458,6 +459,7 @@ function PromptInputButton({ className, tooltip, variant = "ghost", color = "neu
|
|
|
458
459
|
size: resolvedSize,
|
|
459
460
|
className: cx("prompt-input__button", className),
|
|
460
461
|
"aria-label": fallbackLabel,
|
|
462
|
+
"data-responsive-label": hasResponsiveLabel || void 0,
|
|
461
463
|
...props,
|
|
462
464
|
children
|
|
463
465
|
});
|
|
@@ -478,10 +480,14 @@ function PromptInputButton({ className, tooltip, variant = "ghost", color = "neu
|
|
|
478
480
|
* Voice-dictation control for PromptInput. Final upstream transcripts are
|
|
479
481
|
* appended to the composer while interim text remains ephemeral.
|
|
480
482
|
*/
|
|
481
|
-
function PromptInputDictation({ voice, className, disabled, ref, ...props }) {
|
|
483
|
+
function PromptInputDictation({ voice, beforeStart, className, disabled, ref, ...props }) {
|
|
482
484
|
const controller = useOptionalPromptInputController();
|
|
485
|
+
const attachments = usePromptInputAttachments();
|
|
483
486
|
const buttonRef = React.useRef(null);
|
|
484
487
|
const committedTranscriptRef = React.useRef("");
|
|
488
|
+
const submitAfterStopRef = React.useRef(false);
|
|
489
|
+
const recordingStartedAtRef = React.useRef(null);
|
|
490
|
+
const [elapsedSeconds, setElapsedSeconds] = React.useState(0);
|
|
485
491
|
const [isStarting, setIsStarting] = React.useState(false);
|
|
486
492
|
const [startError, setStartError] = React.useState(null);
|
|
487
493
|
React.useImperativeHandle(ref, () => buttonRef.current, []);
|
|
@@ -501,49 +507,195 @@ function PromptInputDictation({ voice, className, disabled, ref, ...props }) {
|
|
|
501
507
|
textarea.value = appendDictationTranscript(textarea.value, addition);
|
|
502
508
|
textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
503
509
|
}, [controller, voice.transcript]);
|
|
510
|
+
React.useEffect(() => {
|
|
511
|
+
if (!voice.isListening) {
|
|
512
|
+
recordingStartedAtRef.current = null;
|
|
513
|
+
setElapsedSeconds(0);
|
|
514
|
+
if (submitAfterStopRef.current) {
|
|
515
|
+
submitAfterStopRef.current = false;
|
|
516
|
+
window.requestAnimationFrame(() => buttonRef.current?.form?.requestSubmit());
|
|
517
|
+
}
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
recordingStartedAtRef.current ??= Date.now();
|
|
521
|
+
const updateElapsed = () => {
|
|
522
|
+
setElapsedSeconds(Math.floor((Date.now() - (recordingStartedAtRef.current ?? Date.now())) / 1e3));
|
|
523
|
+
};
|
|
524
|
+
updateElapsed();
|
|
525
|
+
const timer = window.setInterval(updateElapsed, 250);
|
|
526
|
+
return () => window.clearInterval(timer);
|
|
527
|
+
}, [voice.isListening]);
|
|
504
528
|
const error = startError ?? voice.error;
|
|
505
529
|
const listening = voice.isListening;
|
|
506
530
|
const label = listening ? "Stop dictation" : error ? "Retry dictation" : "Start dictation";
|
|
507
531
|
const status = error ? `Dictation failed: ${error}` : listening ? voice.interimTranscript ? "Listening. Speech detected." : "Listening for speech." : isStarting ? "Starting dictation." : "";
|
|
508
532
|
const level = Math.min(Math.max(voice.audioLevel, 0), 1);
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
533
|
+
const elapsed = formatDictationElapsed(elapsedSeconds);
|
|
534
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
535
|
+
/* @__PURE__ */ jsx(PromptInputButton, {
|
|
536
|
+
ref: buttonRef,
|
|
537
|
+
className: cx("prompt-input__dictation", className),
|
|
538
|
+
tooltip: {
|
|
539
|
+
content: label,
|
|
540
|
+
side: "top"
|
|
541
|
+
},
|
|
542
|
+
"aria-label": label,
|
|
543
|
+
"aria-hidden": listening || void 0,
|
|
544
|
+
"aria-pressed": listening,
|
|
545
|
+
"data-error": error ? "true" : void 0,
|
|
546
|
+
"data-listening": listening ? "true" : void 0,
|
|
547
|
+
"data-starting": isStarting ? "true" : void 0,
|
|
548
|
+
disabled: disabled || isStarting || listening,
|
|
549
|
+
tabIndex: listening ? -1 : void 0,
|
|
550
|
+
onClick: () => {
|
|
551
|
+
setStartError(null);
|
|
552
|
+
if (listening) {
|
|
553
|
+
voice.stop();
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
setIsStarting(true);
|
|
557
|
+
Promise.resolve().then(() => beforeStart?.(voice)).then(() => voice.start()).catch((reason) => {
|
|
558
|
+
setStartError(reason instanceof Error ? reason.message : String(reason));
|
|
559
|
+
}).finally(() => setIsStarting(false));
|
|
560
|
+
},
|
|
561
|
+
...props,
|
|
562
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
563
|
+
className: "prompt-input__dictation-icon",
|
|
564
|
+
style: { "--prompt-input-dictation-level": level },
|
|
565
|
+
"aria-hidden": "true",
|
|
566
|
+
children: isStarting ? /* @__PURE__ */ jsx(SpinnerIcon, {}) : listening ? /* @__PURE__ */ jsx(StopIcon, {}) : /* @__PURE__ */ jsx(MicrophoneIcon, {})
|
|
567
|
+
})
|
|
568
|
+
}),
|
|
569
|
+
listening ? /* @__PURE__ */ jsxs("div", {
|
|
570
|
+
className: "prompt-input__recording",
|
|
571
|
+
role: "group",
|
|
572
|
+
"aria-label": "Voice recording controls",
|
|
573
|
+
children: [
|
|
574
|
+
/* @__PURE__ */ jsx(PromptInputButton, {
|
|
575
|
+
className: "prompt-input__recording-add",
|
|
576
|
+
tooltip: "Add photos or files",
|
|
577
|
+
onClick: () => attachments.openFileDialog(),
|
|
578
|
+
children: /* @__PURE__ */ jsx(PlusIcon, {})
|
|
579
|
+
}),
|
|
580
|
+
/* @__PURE__ */ jsx(PromptInputRecordingWaveform, {
|
|
581
|
+
active: true,
|
|
582
|
+
level
|
|
583
|
+
}),
|
|
584
|
+
/* @__PURE__ */ jsx("time", {
|
|
585
|
+
className: "prompt-input__recording-time",
|
|
586
|
+
dateTime: `PT${elapsedSeconds}S`,
|
|
587
|
+
children: elapsed
|
|
588
|
+
}),
|
|
589
|
+
/* @__PURE__ */ jsx(Button, {
|
|
590
|
+
className: "prompt-input__recording-button",
|
|
591
|
+
type: "button",
|
|
592
|
+
variant: "normal",
|
|
593
|
+
color: "neutral",
|
|
594
|
+
size: "icon",
|
|
595
|
+
"aria-label": "Stop dictation",
|
|
596
|
+
onClick: () => voice.stop(),
|
|
597
|
+
children: /* @__PURE__ */ jsx(SquareIcon, { size: 12 })
|
|
598
|
+
}),
|
|
599
|
+
/* @__PURE__ */ jsx(Button, {
|
|
600
|
+
className: "prompt-input__recording-button",
|
|
601
|
+
type: "button",
|
|
602
|
+
color: "primary",
|
|
603
|
+
size: "icon",
|
|
604
|
+
"aria-label": "Stop dictation and send",
|
|
605
|
+
onClick: () => {
|
|
606
|
+
submitAfterStopRef.current = true;
|
|
607
|
+
voice.stop();
|
|
608
|
+
},
|
|
609
|
+
children: /* @__PURE__ */ jsx(ArrowUpIcon, { size: 18 })
|
|
610
|
+
})
|
|
611
|
+
]
|
|
612
|
+
}) : null,
|
|
613
|
+
/* @__PURE__ */ jsx("span", {
|
|
614
|
+
className: "prompt-input__dictation-status",
|
|
615
|
+
role: "status",
|
|
616
|
+
"aria-live": "polite",
|
|
617
|
+
"aria-atomic": "true",
|
|
618
|
+
children: status
|
|
619
|
+
})
|
|
620
|
+
] });
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Scrolling canvas waveform adapted from ElevenLabs UI's Waveform component.
|
|
624
|
+
* Cloudflare Voice already owns the microphone stream, so this renderer
|
|
625
|
+
* consumes its upstream `audioLevel` instead of requesting a second stream.
|
|
626
|
+
*/
|
|
627
|
+
function PromptInputRecordingWaveform({ active, level }) {
|
|
628
|
+
const canvasRef = React.useRef(null);
|
|
629
|
+
const containerRef = React.useRef(null);
|
|
630
|
+
const historyRef = React.useRef([]);
|
|
631
|
+
const levelRef = React.useRef(level);
|
|
632
|
+
levelRef.current = level;
|
|
633
|
+
React.useEffect(() => {
|
|
634
|
+
const canvas = canvasRef.current;
|
|
635
|
+
const container = containerRef.current;
|
|
636
|
+
if (!canvas || !container) return;
|
|
637
|
+
const resize = () => {
|
|
638
|
+
const rect = container.getBoundingClientRect();
|
|
639
|
+
const dpr = window.devicePixelRatio || 1;
|
|
640
|
+
canvas.width = Math.max(1, Math.round(rect.width * dpr));
|
|
641
|
+
canvas.height = Math.max(1, Math.round(rect.height * dpr));
|
|
642
|
+
canvas.style.width = `${rect.width}px`;
|
|
643
|
+
canvas.style.height = `${rect.height}px`;
|
|
644
|
+
canvas.getContext("2d")?.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
645
|
+
};
|
|
646
|
+
const observer = new ResizeObserver(resize);
|
|
647
|
+
observer.observe(container);
|
|
648
|
+
resize();
|
|
649
|
+
const barWidth = 2;
|
|
650
|
+
const step = 4;
|
|
651
|
+
let animationFrame = 0;
|
|
652
|
+
let lastUpdate = 0;
|
|
653
|
+
let smoothedLevel = levelRef.current;
|
|
654
|
+
const draw = (time) => {
|
|
655
|
+
const context = canvas.getContext("2d");
|
|
656
|
+
const rect = canvas.getBoundingClientRect();
|
|
657
|
+
if (!context || rect.width === 0 || rect.height === 0) {
|
|
658
|
+
animationFrame = window.requestAnimationFrame(draw);
|
|
526
659
|
return;
|
|
527
660
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
661
|
+
const barCount = Math.max(1, Math.floor(rect.width / step));
|
|
662
|
+
if (active && time - lastUpdate >= 50) {
|
|
663
|
+
smoothedLevel += (levelRef.current - smoothedLevel) * .45;
|
|
664
|
+
historyRef.current.push(Math.max(.08, Math.min(1, smoothedLevel)));
|
|
665
|
+
if (historyRef.current.length > barCount) historyRef.current.shift();
|
|
666
|
+
lastUpdate = time;
|
|
667
|
+
}
|
|
668
|
+
context.clearRect(0, 0, rect.width, rect.height);
|
|
669
|
+
context.fillStyle = getComputedStyle(canvas).color;
|
|
670
|
+
const centerY = rect.height / 2;
|
|
671
|
+
for (let index = 0; index < barCount; index += 1) {
|
|
672
|
+
const historyIndex = historyRef.current.length - barCount + index;
|
|
673
|
+
const value = historyIndex >= 0 ? historyRef.current[historyIndex] ?? .08 : .08;
|
|
674
|
+
const barHeight = Math.max(2, value * rect.height * .9);
|
|
675
|
+
const x = index * step;
|
|
676
|
+
context.globalAlpha = .45 + value * .55;
|
|
677
|
+
context.beginPath();
|
|
678
|
+
context.roundRect(x, centerY - barHeight / 2, barWidth, barHeight, 1);
|
|
679
|
+
context.fill();
|
|
680
|
+
}
|
|
681
|
+
context.globalAlpha = 1;
|
|
682
|
+
animationFrame = window.requestAnimationFrame(draw);
|
|
683
|
+
};
|
|
684
|
+
animationFrame = window.requestAnimationFrame(draw);
|
|
685
|
+
return () => {
|
|
686
|
+
observer.disconnect();
|
|
687
|
+
window.cancelAnimationFrame(animationFrame);
|
|
688
|
+
};
|
|
689
|
+
}, [active]);
|
|
690
|
+
return /* @__PURE__ */ jsx("div", {
|
|
691
|
+
ref: containerRef,
|
|
692
|
+
className: "prompt-input__recording-waveform",
|
|
693
|
+
"aria-hidden": "true",
|
|
694
|
+
children: /* @__PURE__ */ jsx("canvas", { ref: canvasRef })
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
function formatDictationElapsed(totalSeconds) {
|
|
698
|
+
return `${Math.floor(totalSeconds / 60)}:${(totalSeconds % 60).toString().padStart(2, "0")}`;
|
|
547
699
|
}
|
|
548
700
|
function appendDictationTranscript(current, transcript) {
|
|
549
701
|
if (!current) return transcript;
|
|
@@ -635,23 +787,38 @@ const PERMISSION_MODES = [{
|
|
|
635
787
|
*/
|
|
636
788
|
function PromptInputPermissionSelector({ value, onValueChange, question = "How should agent actions be approved?" }) {
|
|
637
789
|
const selected = PERMISSION_MODES.find((mode) => mode.value === value) ?? PERMISSION_MODES[0];
|
|
638
|
-
|
|
790
|
+
const trigger = /* @__PURE__ */ jsx(Menu.Trigger, {
|
|
639
791
|
unstyled: true,
|
|
640
792
|
render: /* @__PURE__ */ jsxs(PromptInputButton, {
|
|
641
793
|
size: "xs",
|
|
642
794
|
className: "prompt-input__permissions-trigger",
|
|
643
795
|
"data-mode": value,
|
|
644
796
|
"aria-label": selected.label,
|
|
645
|
-
children: [
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
797
|
+
children: [
|
|
798
|
+
/* @__PURE__ */ jsx("span", {
|
|
799
|
+
className: "prompt-input__permissions-icon",
|
|
800
|
+
children: value === "bypass" ? /* @__PURE__ */ jsx(WarningIcon, { size: 14 }) : /* @__PURE__ */ jsx(WrenchIcon, { size: 14 })
|
|
801
|
+
}),
|
|
802
|
+
/* @__PURE__ */ jsx("span", {
|
|
803
|
+
className: "prompt-input__permissions-current",
|
|
804
|
+
children: PERMISSION_MODES.map((mode) => /* @__PURE__ */ jsx("span", {
|
|
805
|
+
className: "prompt-input__permissions-current-option",
|
|
806
|
+
"data-active": mode.value === value || void 0,
|
|
807
|
+
children: mode.label
|
|
808
|
+
}, mode.value))
|
|
809
|
+
}),
|
|
810
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, {
|
|
811
|
+
className: "prompt-input__permissions-chevron",
|
|
812
|
+
size: 12
|
|
813
|
+
})
|
|
814
|
+
]
|
|
653
815
|
})
|
|
654
|
-
})
|
|
816
|
+
});
|
|
817
|
+
return /* @__PURE__ */ jsxs(Menu.Root, { children: [/* @__PURE__ */ jsxs(Tooltip.Root, { children: [/* @__PURE__ */ jsx(Tooltip.Trigger, { render: trigger }), /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsx(Tooltip.Positioner, {
|
|
818
|
+
side: "top",
|
|
819
|
+
sideOffset: 6,
|
|
820
|
+
children: /* @__PURE__ */ jsx(Tooltip.Popup, { children: selected.label })
|
|
821
|
+
}) })] }), /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, { children: /* @__PURE__ */ jsxs(Menu.Popup, {
|
|
655
822
|
className: "prompt-input__permissions-menu",
|
|
656
823
|
children: [/* @__PURE__ */ jsx("div", {
|
|
657
824
|
className: "prompt-input__permissions-question",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as AgentChatRenderPartContext, r as AgentChatProps } from "../AgentChat-
|
|
1
|
+
import { a as AgentChatRenderPartContext, r as AgentChatProps } from "../AgentChat-Cgb1xuT7.js";
|
|
2
2
|
import { n as BrowserLiveViewProps, t as BrowserLiveView } from "../BrowserLiveView-BV5qgFgI.js";
|
|
3
3
|
import { n as BrowserReplayProps, t as BrowserReplay } from "../BrowserReplay-xWvRjRAC.js";
|
|
4
4
|
import { _ as isThinkChatActivityPart } from "../ThinkChatToolParts-Cv4o7j6F.js";
|
|
5
|
-
import { a as ThinkChatToolRenderers, c as renderThinkChatActivityPart, i as ThinkChatToolRenderer, n as ThinkChatActivityProps, o as createThinkChatActivityRenderer, r as ThinkChatActivityRendererOptions, s as describeThinkChatActivityPart, t as ThinkChatActivity } from "../ThinkChatActivity-
|
|
5
|
+
import { a as ThinkChatToolRenderers, c as renderThinkChatActivityPart, i as ThinkChatToolRenderer, n as ThinkChatActivityProps, o as createThinkChatActivityRenderer, r as ThinkChatActivityRendererOptions, s as describeThinkChatActivityPart, t as ThinkChatActivity } from "../ThinkChatActivity-m9orbdeI.js";
|
|
6
6
|
import { n as ThinkChatValue } from "../ThinkChatContext-C3Eb1Xpi.js";
|
|
7
7
|
import { FileInfo, UseWorkspaceOptions, WorkspaceExplorer, WorkspaceExplorerProps, WorkspaceFileState, WorkspaceInfo, WorkspaceSource, WorkspaceState, inferWorkspaceLanguage, useWorkspace } from "./WorkspaceExplorer.js";
|
|
8
8
|
import * as React from "react";
|
|
@@ -10,6 +10,7 @@ import { UIMessage } from "ai";
|
|
|
10
10
|
import { UseAgentOptions } from "agents/react";
|
|
11
11
|
import { PendingApproval, Think } from "@cloudflare/think";
|
|
12
12
|
import { AgentStub } from "agents/client";
|
|
13
|
+
import { UseVoiceInputReturn } from "@cloudflare/voice/react";
|
|
13
14
|
|
|
14
15
|
//#region src/components/ThinkChat.d.ts
|
|
15
16
|
interface ThinkChatProviderProps<State = unknown, MessageT extends UIMessage = UIMessage> {
|
|
@@ -32,6 +33,10 @@ interface ThinkChatMessagesProps<MessageT extends UIMessage = UIMessage> extends
|
|
|
32
33
|
emptyState?: React.ReactNode;
|
|
33
34
|
/** Extra controls rendered inside the composer, next to the send button. */
|
|
34
35
|
composerTools?: React.ReactNode;
|
|
36
|
+
/** Whole upstream `useVoiceInput` result for the built-in microphone recorder. */
|
|
37
|
+
voiceInput?: UseVoiceInputReturn;
|
|
38
|
+
/** Host prerequisite run before the built-in recorder calls `voiceInput.start()`. */
|
|
39
|
+
beforeVoiceStart?: AgentChatProps<MessageT>["beforeVoiceStart"];
|
|
35
40
|
/** Optional product state rendered in the PromptInput header, such as an Activity. */
|
|
36
41
|
composerHeader?: AgentChatProps<MessageT>["composerHeader"];
|
|
37
42
|
/** Extra rows rendered in the built-in plus menu after files. */
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { _ as isThinkChatActivityPart } from "../ThinkChatToolParts-Cv4o7j6F.js";
|
|
2
|
-
import { a as ThinkChatToolRenderers, c as renderThinkChatActivityPart, i as ThinkChatToolRenderer, n as ThinkChatActivityProps, o as createThinkChatActivityRenderer, r as ThinkChatActivityRendererOptions, s as describeThinkChatActivityPart, t as ThinkChatActivity } from "../ThinkChatActivity-
|
|
2
|
+
import { a as ThinkChatToolRenderers, c as renderThinkChatActivityPart, i as ThinkChatToolRenderer, n as ThinkChatActivityProps, o as createThinkChatActivityRenderer, r as ThinkChatActivityRendererOptions, s as describeThinkChatActivityPart, t as ThinkChatActivity } from "../ThinkChatActivity-m9orbdeI.js";
|
|
3
3
|
export { ThinkChatActivity, ThinkChatActivityProps, ThinkChatActivityRendererOptions, ThinkChatToolRenderer, ThinkChatToolRenderers, createThinkChatActivityRenderer, describeThinkChatActivityPart, isThinkChatActivityPart, renderThinkChatActivityPart };
|
package/dist/styles/activity.css
CHANGED
|
@@ -4,11 +4,15 @@
|
|
|
4
4
|
display: flex;
|
|
5
5
|
flex-direction: column;
|
|
6
6
|
width: 100%;
|
|
7
|
+
min-width: 0;
|
|
7
8
|
/* Hard cap, Codex-style, on the WHOLE unit — collapsed line and expanded
|
|
8
9
|
log alike — so toggling never reflows the conversation width. Plain rem,
|
|
9
10
|
not min(100%, …): percentages are ignored in intrinsic-size contributions,
|
|
10
11
|
so the min() let wide nowrap rows inflate content-sized ancestors. */
|
|
11
12
|
max-width: 36rem;
|
|
13
|
+
/* Live tool labels and panels must never contribute a wider intrinsic size
|
|
14
|
+
when Activity is inserted into a narrow chat transcript. */
|
|
15
|
+
contain: inline-size;
|
|
12
16
|
/* Whitespace separates the work log from message prose around it */
|
|
13
17
|
margin-block: 0.5rem;
|
|
14
18
|
font-family: inherit;
|
|
@@ -17,6 +21,8 @@
|
|
|
17
21
|
|
|
18
22
|
.activity__trigger {
|
|
19
23
|
display: flex;
|
|
24
|
+
width: 100%;
|
|
25
|
+
min-width: 0;
|
|
20
26
|
align-items: center;
|
|
21
27
|
gap: var(--sigvelo-spacing-1-5);
|
|
22
28
|
padding-block: var(--sigvelo-spacing-1-5);
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
position: relative;
|
|
4
4
|
width: 100%;
|
|
5
5
|
height: 100%;
|
|
6
|
+
min-width: 0;
|
|
6
7
|
min-height: 0;
|
|
7
8
|
background-color: var(--sigvelo-color-surface);
|
|
8
9
|
color: var(--sigvelo-color-text);
|
|
@@ -10,6 +11,7 @@
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
.agent-chat__conversation {
|
|
14
|
+
min-width: 0;
|
|
13
15
|
height: 100%;
|
|
14
16
|
min-height: 0;
|
|
15
17
|
}
|
|
@@ -18,6 +20,8 @@
|
|
|
18
20
|
--agent-chat-composer-size is set from a ResizeObserver in AgentChat. */
|
|
19
21
|
.agent-chat__transcript-content {
|
|
20
22
|
gap: 0.875rem;
|
|
23
|
+
min-inline-size: 0;
|
|
24
|
+
max-inline-size: 100%;
|
|
21
25
|
inline-size: min(100%, var(--agent-chat-content-max-inline-size));
|
|
22
26
|
margin-inline: auto;
|
|
23
27
|
padding-block: 1rem calc(var(--agent-chat-composer-size, 5rem) + 0.5rem);
|
|
@@ -35,7 +39,9 @@
|
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
.agent-chat__scroll-button {
|
|
38
|
-
inset-block-end: calc(
|
|
42
|
+
--message-scroller-button-inset-block-end: calc(
|
|
43
|
+
var(--agent-chat-composer-size, 5rem) + var(--sigvelo-spacing-2)
|
|
44
|
+
);
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
/* Floating over the transcript: solid behind the controls, fading out
|
package/dist/styles/message.css
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
flex-direction: column;
|
|
4
4
|
gap: 0.25rem;
|
|
5
5
|
width: 100%;
|
|
6
|
+
min-width: 0;
|
|
6
7
|
font-family: inherit;
|
|
7
8
|
color: var(--sigvelo-color-text);
|
|
8
9
|
}
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
.message__content {
|
|
21
22
|
display: inline-block;
|
|
22
23
|
max-width: min(42rem, 85%);
|
|
24
|
+
min-width: 0;
|
|
23
25
|
padding-block: 0.5rem;
|
|
24
26
|
padding-inline: var(--sigvelo-spacing-3);
|
|
25
27
|
border-radius: var(--sigvelo-radius-lg);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
.prompt-input {
|
|
2
|
+
container: prompt-input / inline-size;
|
|
3
|
+
position: relative;
|
|
2
4
|
display: flex;
|
|
3
5
|
flex-direction: column;
|
|
4
6
|
gap: var(--sigvelo-spacing-1-5);
|
|
@@ -17,6 +19,55 @@
|
|
|
17
19
|
box-shadow var(--sigvelo-duration-fast) var(--sigvelo-ease-standard);
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
.prompt-input__recording {
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: var(--sigvelo-spacing-2);
|
|
26
|
+
flex: 1;
|
|
27
|
+
min-width: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.prompt-input__recording-add {
|
|
31
|
+
flex: 0 0 auto;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.prompt-input__recording-waveform {
|
|
35
|
+
flex: 1 1 auto;
|
|
36
|
+
min-inline-size: 0;
|
|
37
|
+
block-size: var(--sigvelo-spacing-4);
|
|
38
|
+
color: var(--sigvelo-color-text);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.prompt-input__recording-waveform canvas {
|
|
42
|
+
display: block;
|
|
43
|
+
inline-size: 100%;
|
|
44
|
+
block-size: 100%;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.prompt-input__recording-time {
|
|
48
|
+
min-inline-size: 2.5rem;
|
|
49
|
+
color: var(--sigvelo-color-text-muted);
|
|
50
|
+
font-variant-numeric: tabular-nums;
|
|
51
|
+
font-size: var(--sigvelo-text-sm);
|
|
52
|
+
text-align: end;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.prompt-input__recording-button {
|
|
56
|
+
flex: 0 0 auto;
|
|
57
|
+
border-radius: var(--sigvelo-radius-full);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.prompt-input__tools:has(.prompt-input__recording) {
|
|
61
|
+
flex: 1;
|
|
62
|
+
flex-wrap: nowrap;
|
|
63
|
+
width: 100%;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.prompt-input__tools:has(.prompt-input__recording) > :not(.prompt-input__recording),
|
|
67
|
+
.prompt-input__footer:has(.prompt-input__recording) > :not(.prompt-input__tools) {
|
|
68
|
+
display: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
20
71
|
.prompt-input__file-input {
|
|
21
72
|
position: fixed;
|
|
22
73
|
inline-size: 1px;
|
|
@@ -288,6 +339,13 @@
|
|
|
288
339
|
gap: 0.25rem;
|
|
289
340
|
}
|
|
290
341
|
|
|
342
|
+
.prompt-input__permissions-icon {
|
|
343
|
+
display: inline-flex;
|
|
344
|
+
align-items: center;
|
|
345
|
+
justify-content: center;
|
|
346
|
+
flex: 0 0 auto;
|
|
347
|
+
}
|
|
348
|
+
|
|
291
349
|
.prompt-input__permissions-trigger:hover,
|
|
292
350
|
.prompt-input__permissions-trigger[data-popup-open] {
|
|
293
351
|
background-color: color-mix(in oklab, transparent, var(--sigvelo-color-text) 5%);
|
|
@@ -314,6 +372,38 @@
|
|
|
314
372
|
white-space: nowrap;
|
|
315
373
|
}
|
|
316
374
|
|
|
375
|
+
@container prompt-input (max-width: 36rem) {
|
|
376
|
+
.prompt-input__footer {
|
|
377
|
+
gap: var(--sigvelo-spacing-1);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.prompt-input__tools {
|
|
381
|
+
min-width: 0;
|
|
382
|
+
flex-wrap: nowrap;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.prompt-input__button[data-responsive-label] {
|
|
386
|
+
inline-size: 2.75rem;
|
|
387
|
+
min-block-size: 2.75rem;
|
|
388
|
+
padding-inline: 0;
|
|
389
|
+
border-radius: var(--sigvelo-radius-full);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.prompt-input__button[data-responsive-label] > span,
|
|
393
|
+
.prompt-input__permissions-current,
|
|
394
|
+
.prompt-input__permissions-chevron {
|
|
395
|
+
display: none;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.prompt-input__permissions-trigger {
|
|
399
|
+
inline-size: 2.75rem;
|
|
400
|
+
min-block-size: 2.75rem;
|
|
401
|
+
padding-inline: 0;
|
|
402
|
+
justify-content: center;
|
|
403
|
+
border-radius: var(--sigvelo-radius-full);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
317
407
|
.prompt-input__permissions-current-option:not([data-active]) {
|
|
318
408
|
visibility: hidden;
|
|
319
409
|
}
|
|
@@ -21,6 +21,16 @@
|
|
|
21
21
|
overflow-wrap: anywhere;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
.message[data-from="user"] [data-streamdown="link"] {
|
|
25
|
+
color: var(--sigvelo-color-primary-text-on-bg);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
[data-streamdown="link"]:focus-visible {
|
|
29
|
+
outline: var(--sigvelo-focus-width) solid currentColor;
|
|
30
|
+
outline-offset: var(--sigvelo-focus-offset);
|
|
31
|
+
border-radius: var(--sigvelo-radius-xs);
|
|
32
|
+
}
|
|
33
|
+
|
|
24
34
|
/* Links render as <button> when link safety is enabled. */
|
|
25
35
|
button[data-streamdown="link"] {
|
|
26
36
|
appearance: none;
|
|
@@ -78,7 +78,7 @@ declare const CHECKED_IN_CODEX_MODELS: readonly [{
|
|
|
78
78
|
readonly upgradeInfo: null;
|
|
79
79
|
readonly availabilityNux: null;
|
|
80
80
|
readonly hidden: boolean;
|
|
81
|
-
readonly inputModalities: ("
|
|
81
|
+
readonly inputModalities: ("text" | "image")[];
|
|
82
82
|
readonly supportsPersonality: boolean;
|
|
83
83
|
readonly additionalSpeedTiers: never[];
|
|
84
84
|
readonly serviceTiers: never[];
|
|
@@ -98,7 +98,7 @@ declare const CHECKED_IN_CODEX_MODELS: readonly [{
|
|
|
98
98
|
readonly upgradeInfo: null;
|
|
99
99
|
readonly availabilityNux: null;
|
|
100
100
|
readonly hidden: boolean;
|
|
101
|
-
readonly inputModalities: ("
|
|
101
|
+
readonly inputModalities: ("text" | "image")[];
|
|
102
102
|
readonly supportsPersonality: boolean;
|
|
103
103
|
readonly additionalSpeedTiers: never[];
|
|
104
104
|
readonly serviceTiers: never[];
|
|
@@ -115,7 +115,7 @@ declare const CHECKED_IN_CODEX_MODELS: readonly [{
|
|
|
115
115
|
readonly upgradeInfo: null;
|
|
116
116
|
readonly availabilityNux: null;
|
|
117
117
|
readonly hidden: boolean;
|
|
118
|
-
readonly inputModalities: ("
|
|
118
|
+
readonly inputModalities: ("text" | "image")[];
|
|
119
119
|
readonly supportsPersonality: boolean;
|
|
120
120
|
readonly additionalSpeedTiers: never[];
|
|
121
121
|
readonly serviceTiers: never[];
|
|
@@ -132,7 +132,7 @@ declare const CHECKED_IN_CODEX_MODELS: readonly [{
|
|
|
132
132
|
readonly upgradeInfo: null;
|
|
133
133
|
readonly availabilityNux: null;
|
|
134
134
|
readonly hidden: boolean;
|
|
135
|
-
readonly inputModalities: ("
|
|
135
|
+
readonly inputModalities: ("text" | "image")[];
|
|
136
136
|
readonly supportsPersonality: boolean;
|
|
137
137
|
readonly additionalSpeedTiers: never[];
|
|
138
138
|
readonly serviceTiers: never[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-b/react-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "MCP-B React components built on Base UI and shared design tokens, including Cloudflare Think chat primitives.",
|
|
5
5
|
"homepage": "https://design-system.sigvelo.com",
|
|
6
6
|
"bugs": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"lucide-react": "^1.23.0",
|
|
54
54
|
"shiki": "^3.23.0",
|
|
55
55
|
"streamdown": "^2.5.0",
|
|
56
|
-
"@mcp-b/design-tokens": "0.
|
|
56
|
+
"@mcp-b/design-tokens": "0.14.1"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@ai-sdk/react": "^3.0.222",
|