@blocksdiy/react-common 1.28.0 → 1.28.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.
@@ -1,7 +1,8 @@
1
- import { type Message, type UserMessage } from "@ag-ui/client";
1
+ import { type Message, ToolMessage, type UserMessage } from "@ag-ui/client";
2
+ import { useRenderToolCall } from "@copilotkit/react-core/v2";
2
3
  import { ReactNode, SetStateAction } from "react";
3
- export { type Message, type AssistantMessage } from "@ag-ui/client";
4
- export { useRenderTool, useRenderToolCall, useDefaultRenderTool, useHumanInTheLoop, useFrontendTool, ToolCallStatus, } from "@copilotkit/react-core/v2";
4
+ export { type Message, type AssistantMessage, type UserMessage } from "@ag-ui/client";
5
+ export { useRenderTool, useDefaultRenderTool, useHumanInTheLoop, useFrontendTool, ToolCallStatus, } from "@copilotkit/react-core/v2";
5
6
  export interface Attachment {
6
7
  url: string;
7
8
  fileType: string;
@@ -10,8 +11,7 @@ export interface Attachment {
10
11
  export interface AgentChatComponent {
11
12
  id: string;
12
13
  name: string;
13
- toolName?: string;
14
- code?: string;
14
+ code: string;
15
15
  input?: Record<string, unknown>;
16
16
  description?: string;
17
17
  /**
@@ -51,6 +51,14 @@ export interface AgentChatContextValue {
51
51
  agent: Agent | null;
52
52
  agentChat: AgentChat | null;
53
53
  components: AgentChatComponent[];
54
+ messageGroups: {
55
+ messageIds: string[];
56
+ role: "assistant" | "user";
57
+ }[];
58
+ messageById: Map<string, Message>;
59
+ toolMessages: ToolMessage[];
60
+ renderToolCall: ReturnType<typeof useRenderToolCall>;
61
+ hasSentMessageInSession: boolean;
54
62
  sendMessage: (message: Omit<UserMessage, "id" | "role">) => Promise<void>;
55
63
  sendFromInputs: () => Promise<void>;
56
64
  stopGeneration: () => void;
@@ -64,6 +72,11 @@ export interface AgentChatContextValue {
64
72
  }
65
73
  export declare const AgentChatContext: import("react").Context<AgentChatContextValue | null>;
66
74
  export declare const useAgentChat: () => AgentChatContextValue;
75
+ interface AgentChatScrollContextValue {
76
+ isAtBottom: boolean;
77
+ scrollToBottom: () => void;
78
+ }
79
+ export declare const useAgentChatScroll: () => AgentChatScrollContextValue;
67
80
  export interface AgentChatRootProps {
68
81
  appId: string;
69
82
  token?: string;
@@ -88,10 +101,22 @@ export interface AgentChatMessageProps {
88
101
  index: number;
89
102
  }
90
103
  export declare function AgentChatMessage({ message, index, ...props }: React.ComponentProps<"div"> & AgentChatMessageProps): import("react/jsx-runtime").JSX.Element | null;
104
+ export interface AgentChatMessageGroupProps {
105
+ messageGroup: {
106
+ messageIds: string[];
107
+ role: "assistant" | "user";
108
+ };
109
+ isLast?: boolean;
110
+ }
111
+ export declare function AgentChatMessageGroup({ messageGroup, isLast, style, ...props }: React.ComponentProps<"div"> & AgentChatMessageGroupProps): import("react/jsx-runtime").JSX.Element;
91
112
  export interface AgentChatMessagesProps {
92
113
  scrollAreaClassName?: string;
93
114
  }
94
- export declare function AgentChatMessages({ scrollAreaClassName, ...props }: React.ComponentProps<"div"> & AgentChatMessagesProps): import("react/jsx-runtime").JSX.Element;
115
+ export declare function AgentChatMessages({ scrollAreaClassName, children, ...props }: React.ComponentProps<"div"> & AgentChatMessagesProps): import("react/jsx-runtime").JSX.Element;
116
+ export interface AgentChatScrollToBottomProps {
117
+ asChild?: boolean;
118
+ }
119
+ export declare function AgentChatScrollToBottom({ asChild, onClick, ...props }: React.ComponentProps<"button"> & AgentChatScrollToBottomProps): import("react/jsx-runtime").JSX.Element | null;
95
120
  export interface AgentChatThinkingProps {
96
121
  asChild?: boolean;
97
122
  }
@@ -1 +1 @@
1
- {"version":3,"file":"new-agent-chat.d.ts","sourceRoot":"","sources":["../../src/components/new-agent-chat.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"new-agent-chat.d.ts","sourceRoot":"","sources":["../../src/components/new-agent-chat.tsx"],"names":[],"mappings":"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"}
@@ -2,11 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { AppVersionService, BlocksApiService, websocketsService } from "@blocksdiy/blocks-client-api";
3
3
  import { getApiHost } from "@blocksdiy/blocks-client-api/envService";
4
4
  import { CopilotKit, useCopilotChatInternal } from "@copilotkit/react-core";
5
- import { useCopilotKit } from "@copilotkit/react-core/v2";
5
+ import { useCopilotKit, useRenderToolCall } from "@copilotkit/react-core/v2";
6
6
  import { Slot } from "@radix-ui/react-slot";
7
7
  import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
8
- export { useRenderTool, useRenderToolCall, useDefaultRenderTool, useHumanInTheLoop, useFrontendTool, ToolCallStatus, } from "@copilotkit/react-core/v2";
9
- import { useStickToBottom } from "use-stick-to-bottom";
8
+ export { useRenderTool, useDefaultRenderTool, useHumanInTheLoop, useFrontendTool, ToolCallStatus, } from "@copilotkit/react-core/v2";
10
9
  // Client-only `useLayoutEffect`, falls back to `useEffect` during SSR.
11
10
  // Needed so the `agent.threadId` mirror commits before CopilotKit's
12
11
  // connect-on-mount effect reads it.
@@ -61,15 +60,82 @@ const validateAndConvertFiles = (files) => {
61
60
  }
62
61
  const hasOversizedFiles = files.some((file) => file.size > MAX_FILE_SIZE_BYTES);
63
62
  if (hasOversizedFiles) {
64
- console.error(`Upload failed because some files are bigger than ${MAX_FILE_SIZE_MB} MB.`);
65
63
  return null;
66
64
  }
67
65
  return files.map((file) => ({
68
- fileType: file.type,
66
+ fileType: file.type || "application/octet-stream",
69
67
  fileName: file.name,
70
68
  url: URL.createObjectURL(file),
71
69
  }));
72
70
  };
71
+ const fileFromAttachment = async (attachment) => {
72
+ const response = await fetch(attachment.url);
73
+ if (!response.ok) {
74
+ throw new Error("The blob URL is no longer valid");
75
+ }
76
+ const blob = await response.blob();
77
+ return new File([blob], attachment.fileName, {
78
+ type: attachment.fileType,
79
+ lastModified: Date.now(),
80
+ });
81
+ };
82
+ const getBrowserUploadUrl = (uploadUrl) => {
83
+ try {
84
+ const url = new URL(uploadUrl);
85
+ if (url.hostname === "localhost" && url.port === "4566") {
86
+ url.hostname = "blocks.localhost";
87
+ return url.toString();
88
+ }
89
+ }
90
+ catch {
91
+ return uploadUrl;
92
+ }
93
+ return uploadUrl;
94
+ };
95
+ const uploadFile = async ({ appId, blocksApiService, file, }) => {
96
+ const formData = new FormData();
97
+ const { uploadUrl, fields, protectedUrl } = await blocksApiService.getDataAssetUploadUrl({
98
+ productId: appId,
99
+ fileName: file.name,
100
+ fileType: file.type,
101
+ });
102
+ const request = new XMLHttpRequest();
103
+ if (uploadUrl && fields) {
104
+ for (const [key, value] of Object.entries(fields)) {
105
+ formData.append(key, value);
106
+ }
107
+ formData.append("file", file);
108
+ request.open("POST", getBrowserUploadUrl(uploadUrl));
109
+ }
110
+ return new Promise((resolve, reject) => {
111
+ request.onload = () => {
112
+ if (request.status >= 200 && request.status < 300) {
113
+ resolve(protectedUrl);
114
+ }
115
+ else {
116
+ reject(new Error("Error uploading file"));
117
+ }
118
+ };
119
+ request.onerror = () => {
120
+ reject(new Error("Error uploading file"));
121
+ };
122
+ request.send(formData);
123
+ });
124
+ };
125
+ const uploadAttachments = async ({ attachments, blocksApiService, appId, }) => {
126
+ if (!attachments?.length) {
127
+ return undefined;
128
+ }
129
+ return Promise.all(attachments.map(async (attachment) => {
130
+ const file = await fileFromAttachment(attachment);
131
+ const protectedUrl = await uploadFile({ appId, blocksApiService, file });
132
+ return {
133
+ url: protectedUrl,
134
+ fileName: attachment.fileName,
135
+ fileType: attachment.fileType,
136
+ };
137
+ }));
138
+ };
73
139
  const hasSendableInput = (prompt, attachments) => {
74
140
  return prompt.trim().length > 0 || attachments.length > 0;
75
141
  };
@@ -81,6 +147,55 @@ export const useAgentChat = () => {
81
147
  }
82
148
  return context;
83
149
  };
150
+ const NEW_MESSAGE_SCROLL_HIDE_MS = 500;
151
+ const AgentChatScrollContext = createContext(null);
152
+ export const useAgentChatScroll = () => {
153
+ const context = useContext(AgentChatScrollContext);
154
+ if (!context) {
155
+ throw new Error("useAgentChatScroll must be used within an AgentChatMessages provider");
156
+ }
157
+ return context;
158
+ };
159
+ const getMessageGroups = (scrollElement) => {
160
+ return Array.from(scrollElement.querySelectorAll('[data-slot="agent-chat-message-group"]'));
161
+ };
162
+ const SCROLL_BOTTOM_OFFSET_PX = 70;
163
+ const getTargetScrollTop = (scrollElement) => {
164
+ return Math.max(scrollElement.scrollHeight - 1 - scrollElement.clientHeight, 0);
165
+ };
166
+ const isScrollAtBottom = (scrollElement) => {
167
+ return getTargetScrollTop(scrollElement) - scrollElement.scrollTop <= SCROLL_BOTTOM_OFFSET_PX;
168
+ };
169
+ const setScrollTopInstantly = (scrollElement, scrollTop) => {
170
+ const { scrollBehavior } = getComputedStyle(scrollElement);
171
+ if (scrollBehavior !== "auto") {
172
+ scrollElement.style.scrollBehavior = "auto";
173
+ }
174
+ scrollElement.scrollTop = scrollTop;
175
+ if (scrollBehavior !== "auto") {
176
+ scrollElement.style.scrollBehavior = scrollBehavior;
177
+ }
178
+ };
179
+ const AGENT_CHAT_CONTAINER_HEIGHT_VAR = "--agent-chat-container-height";
180
+ const AGENT_CHAT_LATEST_USER_HEIGHT_VAR = "--agent-chat-latest-user-message-height";
181
+ const LAST_ASSISTANT_MESSAGE_GROUP_STYLE = {
182
+ minHeight: `max(calc(var(${AGENT_CHAT_CONTAINER_HEIGHT_VAR}, 0px) - var(${AGENT_CHAT_LATEST_USER_HEIGHT_VAR}, var(${AGENT_CHAT_CONTAINER_HEIGHT_VAR}, 0px))), 0px)`,
183
+ };
184
+ const updateScrollHeightVariables = (scrollElement) => {
185
+ const messageGroups = getMessageGroups(scrollElement);
186
+ const latestUserGroup = messageGroups.reverse().find((messageGroup) => messageGroup.dataset.messageGroup === "user");
187
+ scrollElement.style.setProperty(AGENT_CHAT_CONTAINER_HEIGHT_VAR, `${scrollElement.clientHeight}px`);
188
+ if (latestUserGroup) {
189
+ scrollElement.style.setProperty(AGENT_CHAT_LATEST_USER_HEIGHT_VAR, `${latestUserGroup.offsetHeight}px`);
190
+ }
191
+ else {
192
+ scrollElement.style.removeProperty(AGENT_CHAT_LATEST_USER_HEIGHT_VAR);
193
+ }
194
+ };
195
+ const clearScrollHeightVariables = (scrollElement) => {
196
+ scrollElement.style.removeProperty(AGENT_CHAT_CONTAINER_HEIGHT_VAR);
197
+ scrollElement.style.removeProperty(AGENT_CHAT_LATEST_USER_HEIGHT_VAR);
198
+ };
84
199
  const SessionReadables = () => {
85
200
  // const now = new Date();
86
201
  // useCopilotReadable({
@@ -105,6 +220,33 @@ const ChatInitializer = ({ agentId, agentChatId, chatId, token, appId, component
105
220
  const [isConfigLoaded, setIsConfigLoaded] = useState(false);
106
221
  const { messages: copilotMessages, sendMessage: copilotSendMessage, stopGeneration: copilotStopGeneration, isAvailable: isAgentReady, isLoading: isAgentRunning, agent: copilotAgent, } = useCopilotChatInternal();
107
222
  const { copilotkit } = useCopilotKit();
223
+ const renderToolCall = useRenderToolCall();
224
+ const messageById = useMemo(() => {
225
+ const messagesSet = new Map();
226
+ copilotMessages.forEach((message) => {
227
+ messagesSet.set(message.id, message);
228
+ });
229
+ return messagesSet;
230
+ }, [copilotMessages]);
231
+ const toolMessages = useMemo(() => {
232
+ return copilotMessages.filter((message) => message.role === "tool");
233
+ }, [copilotMessages]);
234
+ const messageGroups = useMemo(() => {
235
+ const groups = [];
236
+ copilotMessages.forEach((message) => {
237
+ if (message.role !== "assistant" && message.role !== "user") {
238
+ return;
239
+ }
240
+ const lastGroup = groups[groups.length - 1];
241
+ if (!lastGroup || lastGroup.role !== message.role) {
242
+ groups.push({ role: message.role, messageIds: [message.id] });
243
+ }
244
+ else {
245
+ lastGroup.messageIds.push(message.id);
246
+ }
247
+ });
248
+ return groups;
249
+ }, [copilotMessages]);
108
250
  // Mirror `currentThreadId` onto the agent instance — the `<CopilotKit>`
109
251
  // prop only feeds React context, but `agent.threadId` is what hits the
110
252
  // wire and the LangGraph checkpoint. `<CopilotChat>` does this for you;
@@ -120,6 +262,7 @@ const ChatInitializer = ({ agentId, agentChatId, chatId, token, appId, component
120
262
  const [prompt, setPrompt] = useState("");
121
263
  const [attachments, setAttachments] = useState([]);
122
264
  const [isDraggingFiles, setIsDraggingFiles] = useState(false);
265
+ const [hasSentMessageInSession, setHasSentMessageInSession] = useState(false);
123
266
  const blocksApiService = useMemo(() => new BlocksApiService({ token }), [token]);
124
267
  const attachmentsEnabled = agentChat ? agentChat.disableAttachments !== true : false;
125
268
  const canSendMessage = Boolean(agentChatId && agentChat && agent && isConfigLoaded && isAgentReady && !isAgentRunning);
@@ -131,6 +274,7 @@ const ChatInitializer = ({ agentId, agentChatId, chatId, token, appId, component
131
274
  if (!canSendMessage) {
132
275
  return Promise.resolve();
133
276
  }
277
+ setHasSentMessageInSession(true);
134
278
  return copilotSendMessage({ id: generateId(), role: "user", ...message });
135
279
  }, [canSendMessage, copilotSendMessage]);
136
280
  const stopGeneration = useCallback(() => {
@@ -151,7 +295,7 @@ const ChatInitializer = ({ agentId, agentChatId, chatId, token, appId, component
151
295
  if (!componentIds?.length) {
152
296
  return [];
153
297
  }
154
- const maybeComponentBlocks = await Promise.all(componentIds.map(async (componentId) => {
298
+ const chatComponentBlocks = await Promise.all(componentIds.map(async (componentId) => {
155
299
  try {
156
300
  const block = await blocksApiService.getBlock(componentId);
157
301
  const id = block?.id ?? componentId;
@@ -167,7 +311,6 @@ const ChatInitializer = ({ agentId, agentChatId, chatId, token, appId, component
167
311
  code,
168
312
  input: block?.data?.input,
169
313
  description,
170
- toolName: getAgentChatComponentToolName(name),
171
314
  userInterrupt: Boolean(block?.data?.userInterrupt),
172
315
  };
173
316
  }
@@ -175,7 +318,7 @@ const ChatInitializer = ({ agentId, agentChatId, chatId, token, appId, component
175
318
  return null;
176
319
  }
177
320
  }));
178
- return maybeComponentBlocks.filter((component) => Boolean(component));
321
+ return chatComponentBlocks.filter((chatComponentBlock) => Boolean(chatComponentBlock));
179
322
  }, [blocksApiService, componentIds]);
180
323
  const componentIdsKey = componentIds?.join(",") ?? "";
181
324
  const initKeyRef = useRef(null);
@@ -198,6 +341,7 @@ const ChatInitializer = ({ agentId, agentChatId, chatId, token, appId, component
198
341
  }
199
342
  initKeyRef.current = initKey;
200
343
  initialPromptSentRef.current = false;
344
+ setHasSentMessageInSession(false);
201
345
  const ac = new AbortController();
202
346
  const initialize = async () => {
203
347
  setIsConfigLoaded(false);
@@ -302,12 +446,45 @@ const ChatInitializer = ({ agentId, agentChatId, chatId, token, appId, component
302
446
  });
303
447
  void copilotkit.runAgent({ agent: copilotAgent });
304
448
  }, [isAgentReady, isConfigLoaded, agentChat, copilotAgent, canSendMessage, copilotkit]);
449
+ const buildMessageContentFromInput = (currentPrompt = prompt, currentAttachments = attachments) => {
450
+ if (currentAttachments.length === 0) {
451
+ return currentPrompt;
452
+ }
453
+ const contentArray = [];
454
+ currentAttachments.forEach((attachment) => {
455
+ const source = { type: "url", value: attachment.url, mimeType: attachment.fileType };
456
+ const metadata = { filename: attachment.fileName };
457
+ switch (true) {
458
+ case attachment.fileType.startsWith("image/"):
459
+ contentArray.push({ type: "image", source, metadata });
460
+ break;
461
+ case attachment.fileType.startsWith("audio/"):
462
+ contentArray.push({ type: "audio", source, metadata });
463
+ break;
464
+ case attachment.fileType.startsWith("video/"):
465
+ contentArray.push({ type: "video", source, metadata });
466
+ break;
467
+ default:
468
+ contentArray.push({ type: "document", source, metadata });
469
+ }
470
+ });
471
+ if (currentPrompt) {
472
+ contentArray.push({ type: "text", text: currentPrompt });
473
+ }
474
+ return contentArray;
475
+ };
305
476
  const sendFromInputs = async () => {
306
477
  if (!canSendMessage || !hasSendableInput(prompt, attachments)) {
307
478
  return;
308
479
  }
309
480
  const currentPrompt = prompt;
310
- // const currentAttachments = attachments;
481
+ const currentAttachments = attachments;
482
+ const uploadedAttachments = await uploadAttachments({
483
+ attachments: currentAttachments,
484
+ appId,
485
+ blocksApiService,
486
+ });
487
+ const messageContent = buildMessageContentFromInput(currentPrompt, uploadedAttachments ?? []);
311
488
  setPrompt("");
312
489
  setAttachments([]);
313
490
  // Auto-skip any frontend user-choice tool call that's still waiting.
@@ -348,7 +525,9 @@ const ChatInitializer = ({ agentId, agentChatId, chatId, token, appId, component
348
525
  });
349
526
  }
350
527
  }
351
- await sendMessage({ content: currentPrompt });
528
+ await sendMessage({
529
+ content: messageContent,
530
+ });
352
531
  };
353
532
  const addAttachments = (attachments) => {
354
533
  if (!attachmentsEnabled) {
@@ -377,6 +556,11 @@ const ChatInitializer = ({ agentId, agentChatId, chatId, token, appId, component
377
556
  };
378
557
  return (_jsx(AgentChatContext.Provider, { value: {
379
558
  messages: copilotMessages,
559
+ messageGroups,
560
+ renderToolCall,
561
+ messageById,
562
+ toolMessages,
563
+ hasSentMessageInSession,
380
564
  prompt,
381
565
  attachments,
382
566
  sendMessage,
@@ -438,24 +622,139 @@ export function AgentChatMessage({ message, index, ...props }) {
438
622
  }
439
623
  return _jsx("div", { "data-message-index": index, "data-message-role": message.role, ...props });
440
624
  }
441
- export function AgentChatMessages({ scrollAreaClassName, ...props }) {
442
- const { messages } = useAgentChat();
443
- const userMessageCount = messages.filter((message) => message.role === "user" && message.name !== HIDDEN_INITIAL_PROMPT_MESSAGE_NAME).length;
444
- const previousUserMessageCountRef = useRef(userMessageCount);
445
- const { scrollRef, contentRef, scrollToBottom } = useStickToBottom({
446
- resize: "smooth",
447
- initial: { damping: 1, stiffness: 1 },
448
- });
625
+ export function AgentChatMessageGroup({ messageGroup, isLast, style, ...props }) {
626
+ const { hasSentMessageInSession, messageGroups } = useAgentChat();
627
+ const lastMessageGroup = messageGroups[messageGroups.length - 1];
628
+ const isLastMessageGroup = isLast ??
629
+ (lastMessageGroup?.role === messageGroup.role &&
630
+ lastMessageGroup.messageIds.length === messageGroup.messageIds.length &&
631
+ lastMessageGroup.messageIds.every((messageId, index) => messageId === messageGroup.messageIds[index]));
632
+ const mergedStyle = hasSentMessageInSession && isLastMessageGroup && messageGroup.role === "assistant"
633
+ ? {
634
+ ...style,
635
+ ...LAST_ASSISTANT_MESSAGE_GROUP_STYLE,
636
+ }
637
+ : style;
638
+ return (_jsx("div", { "data-slot": "agent-chat-message-group", "data-message-group": messageGroup.role, "data-message-group-role": messageGroup.role, style: mergedStyle, ...props }));
639
+ }
640
+ export function AgentChatMessages({ scrollAreaClassName, children, ...props }) {
641
+ const { isFetchingMessages, isThinking, messageGroups } = useAgentChat();
642
+ const messageGroupCount = messageGroups.length;
643
+ const scrollRef = useRef(null);
644
+ const previousMessageGroupCountRef = useRef(messageGroupCount);
645
+ const hasCompletedInitialScrollRef = useRef(false);
646
+ const previousIsThinkingRef = useRef(isThinking);
647
+ const newMessageScrollTimeoutRef = useRef(null);
648
+ const [isNewMessageScrollInProgress, setIsNewMessageScrollInProgress] = useState(false);
649
+ const [isAtBottom, setIsAtBottom] = useState(true);
650
+ const scrollToBottom = useCallback((behavior = "smooth") => {
651
+ const scrollElement = scrollRef.current;
652
+ if (!scrollElement) {
653
+ return;
654
+ }
655
+ const targetScrollTop = getTargetScrollTop(scrollElement);
656
+ if (behavior === "instant") {
657
+ setScrollTopInstantly(scrollElement, targetScrollTop);
658
+ }
659
+ else {
660
+ scrollElement.scrollTo({ top: targetScrollTop, behavior });
661
+ }
662
+ setIsAtBottom(true);
663
+ }, []);
664
+ const scrollContextValue = useMemo(() => ({
665
+ isAtBottom: isAtBottom || isNewMessageScrollInProgress,
666
+ scrollToBottom: () => {
667
+ void scrollToBottom();
668
+ },
669
+ }), [isAtBottom, isNewMessageScrollInProgress, scrollToBottom]);
670
+ useIsomorphicLayoutEffect(() => {
671
+ const scrollElement = scrollRef.current;
672
+ if (!scrollElement) {
673
+ return;
674
+ }
675
+ if (getComputedStyle(scrollElement).overflow === "visible") {
676
+ scrollElement.style.overflow = "auto";
677
+ }
678
+ const updateIsAtBottom = () => {
679
+ setIsAtBottom(isScrollAtBottom(scrollElement));
680
+ };
681
+ updateIsAtBottom();
682
+ scrollElement.addEventListener("scroll", updateIsAtBottom, { passive: true });
683
+ return () => {
684
+ scrollElement.removeEventListener("scroll", updateIsAtBottom);
685
+ };
686
+ }, []);
449
687
  useEffect(() => {
450
- if (userMessageCount > previousUserMessageCountRef.current) {
451
- void scrollToBottom({
452
- animation: "smooth",
453
- ignoreEscapes: true,
454
- });
455
- }
456
- previousUserMessageCountRef.current = userMessageCount;
457
- }, [scrollToBottom, userMessageCount]);
458
- return (_jsx("div", { ref: scrollRef, style: { overflow: "auto" }, className: scrollAreaClassName, children: _jsx("div", { ref: contentRef, "data-slot": "agent-chat-messages", ...props }) }));
688
+ return () => {
689
+ if (newMessageScrollTimeoutRef.current !== null) {
690
+ window.clearTimeout(newMessageScrollTimeoutRef.current);
691
+ }
692
+ };
693
+ }, []);
694
+ useEffect(() => {
695
+ const scrollElement = scrollRef.current;
696
+ const wasThinking = previousIsThinkingRef.current;
697
+ previousIsThinkingRef.current = isThinking;
698
+ if (!scrollElement || isThinking || !wasThinking) {
699
+ return;
700
+ }
701
+ setIsAtBottom(isScrollAtBottom(scrollElement));
702
+ }, [isThinking]);
703
+ useIsomorphicLayoutEffect(() => {
704
+ const scrollElement = scrollRef.current;
705
+ if (isFetchingMessages) {
706
+ previousMessageGroupCountRef.current = messageGroupCount;
707
+ return;
708
+ }
709
+ if (!scrollElement) {
710
+ previousMessageGroupCountRef.current = messageGroupCount;
711
+ return;
712
+ }
713
+ if (!hasCompletedInitialScrollRef.current) {
714
+ clearScrollHeightVariables(scrollElement);
715
+ scrollToBottom("instant");
716
+ previousMessageGroupCountRef.current = messageGroupCount;
717
+ hasCompletedInitialScrollRef.current = true;
718
+ return;
719
+ }
720
+ if (messageGroupCount < previousMessageGroupCountRef.current) {
721
+ previousMessageGroupCountRef.current = messageGroupCount;
722
+ clearScrollHeightVariables(scrollElement);
723
+ scrollToBottom("instant");
724
+ return;
725
+ }
726
+ if (messageGroupCount > previousMessageGroupCountRef.current) {
727
+ updateScrollHeightVariables(scrollElement);
728
+ setIsNewMessageScrollInProgress(true);
729
+ if (newMessageScrollTimeoutRef.current !== null) {
730
+ window.clearTimeout(newMessageScrollTimeoutRef.current);
731
+ }
732
+ newMessageScrollTimeoutRef.current = window.setTimeout(() => {
733
+ setIsNewMessageScrollInProgress(false);
734
+ newMessageScrollTimeoutRef.current = null;
735
+ }, NEW_MESSAGE_SCROLL_HIDE_MS);
736
+ scrollToBottom("smooth");
737
+ }
738
+ previousMessageGroupCountRef.current = messageGroupCount;
739
+ }, [isFetchingMessages, messageGroupCount, scrollToBottom]);
740
+ return (_jsx(AgentChatScrollContext.Provider, { value: scrollContextValue, children: _jsx("div", { ...props, children: _jsx("div", { ref: scrollRef, style: {
741
+ height: "100%",
742
+ width: "100%",
743
+ scrollbarGutter: "stable both-edges",
744
+ }, children: _jsx("div", { className: scrollAreaClassName, children: children }) }) }) }));
745
+ }
746
+ export function AgentChatScrollToBottom({ asChild = false, onClick, ...props }) {
747
+ const { isAtBottom, scrollToBottom } = useAgentChatScroll();
748
+ const Comp = asChild ? Slot : "button";
749
+ if (isAtBottom) {
750
+ return null;
751
+ }
752
+ return (_jsx(Comp, { "data-slot": "agent-chat-scroll-to-bottom", onClick: (event) => {
753
+ onClick?.(event);
754
+ if (!event.defaultPrevented) {
755
+ scrollToBottom();
756
+ }
757
+ }, ...props }));
459
758
  }
460
759
  export function AgentChatThinking({ asChild = false, ...props }) {
461
760
  const { isThinking } = useAgentChat();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocksdiy/react-common",
3
- "version": "1.28.0",
3
+ "version": "1.28.1",
4
4
  "type": "module",
5
5
  "description": "React common",
6
6
  "keywords": [],
@@ -38,7 +38,7 @@
38
38
  "penpal": "^7.0.6",
39
39
  "react": "^19.2.4",
40
40
  "use-stick-to-bottom": "1.1.4",
41
- "@blocksdiy/blocks-client-api": "1.5.0"
41
+ "@blocksdiy/blocks-client-api": "1.10.1"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/react": "^19.2.14",