@ant-design/agentic-ui 2.27.8 → 2.27.10

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.
@@ -22,50 +22,4 @@ export interface AgenticLayoutProps {
22
22
  /** 子元素(用于兼容性,实际内容应使用 center 属性) */
23
23
  children?: ReactNode;
24
24
  }
25
- /**
26
- * AgenticLayout 组件 - 智能体布局组件
27
- *
28
- * 该组件提供一个三栏布局的容器,支持左中右三个区域的灵活配置。
29
- * 左右侧栏支持折叠功能,中间区域自适应宽度。
30
- *
31
- * @component
32
- * @description 智能体布局组件,提供左中右三栏布局
33
- * @param {AgenticLayoutProps} props - 组件属性
34
- * @param {ReactNode} [props.left] - 左侧内容
35
- * @param {ReactNode} props.center - 中间内容
36
- * @param {ReactNode} [props.right] - 右侧内容
37
- * @param {LayoutHeaderConfig} [props.header] - 头部配置
38
- * @param {React.CSSProperties} [props.style] - 自定义样式
39
- * @param {string} [props.className] - 自定义CSS类名
40
- * @param {number} [props.leftWidth=256] - 左侧宽度
41
- * @param {number} [props.rightWidth=256] - 右侧宽度
42
- * @param {string | number} [props.minHeight='600px'] - 最小高度
43
- *
44
- * @example
45
- * ```tsx
46
- * <AgenticLayout
47
- * left={<History />}
48
- * center={<ChatLayout />}
49
- * right={<Workspace />}
50
- * header={{
51
- * title: "智能体助手",
52
- * showShare: true,
53
- * showLeftCollapse: true,
54
- * showRightCollapse: true,
55
- * onLeftCollapse: (collapsed) => console.log('左侧折叠:', collapsed),
56
- * onRightCollapse: (collapsed) => console.log('右侧折叠:', collapsed),
57
- * onShare: () => console.log('分享')
58
- * }}
59
- * />
60
- * ```
61
- *
62
- * @returns {React.ReactElement} 渲染的布局组件
63
- *
64
- * @remarks
65
- * - 支持左右侧栏的独立折叠控制
66
- * - 中间区域自适应剩余宽度
67
- * - 提供响应式布局适配
68
- * - 支持自定义宽度和高度
69
- * - 集成 Ant Design 主题系统
70
- */
71
25
  export declare const AgenticLayout: React.FC<AgenticLayoutProps>;
@@ -1,3 +1,11 @@
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_with_holes(arr) {
7
+ if (Array.isArray(arr)) return arr;
8
+ }
1
9
  function _define_property(obj, key, value) {
2
10
  if (key in obj) {
3
11
  Object.defineProperty(obj, key, {
@@ -11,6 +19,33 @@ function _define_property(obj, key, value) {
11
19
  }
12
20
  return obj;
13
21
  }
22
+ function _iterable_to_array_limit(arr, i) {
23
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
24
+ if (_i == null) return;
25
+ var _arr = [];
26
+ var _n = true;
27
+ var _d = false;
28
+ var _s, _e;
29
+ try {
30
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
31
+ _arr.push(_s.value);
32
+ if (i && _arr.length === i) break;
33
+ }
34
+ } catch (err) {
35
+ _d = true;
36
+ _e = err;
37
+ } finally{
38
+ try {
39
+ if (!_n && _i["return"] != null) _i["return"]();
40
+ } finally{
41
+ if (_d) throw _e;
42
+ }
43
+ }
44
+ return _arr;
45
+ }
46
+ function _non_iterable_rest() {
47
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
48
+ }
14
49
  function _object_spread(target) {
15
50
  for(var i = 1; i < arguments.length; i++){
16
51
  var source = arguments[i] != null ? arguments[i] : {};
@@ -50,8 +85,19 @@ function _object_spread_props(target, source) {
50
85
  }
51
86
  return target;
52
87
  }
88
+ function _sliced_to_array(arr, i) {
89
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
90
+ }
91
+ function _unsupported_iterable_to_array(o, minLen) {
92
+ if (!o) return;
93
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
94
+ var n = Object.prototype.toString.call(o).slice(8, -1);
95
+ if (n === "Object" && o.constructor) n = o.constructor.name;
96
+ if (n === "Map" || n === "Set") return Array.from(n);
97
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
98
+ }
53
99
  import { ConfigProvider } from "antd";
54
- import React, { useContext } from "react";
100
+ import React, { useCallback, useContext, useEffect, useRef, useState } from "react";
55
101
  import { LayoutHeader } from "../Components/LayoutHeader";
56
102
  import { useAgenticLayoutStyle } from "./style";
57
103
  /**
@@ -70,7 +116,7 @@ import { useAgenticLayoutStyle } from "./style";
70
116
  * @param {React.CSSProperties} [props.style] - 自定义样式
71
117
  * @param {string} [props.className] - 自定义CSS类名
72
118
  * @param {number} [props.leftWidth=256] - 左侧宽度
73
- * @param {number} [props.rightWidth=256] - 右侧宽度
119
+ * @param {number} [props.rightWidth=540] - 右侧宽度
74
120
  * @param {string | number} [props.minHeight='600px'] - 最小高度
75
121
  *
76
122
  * @example
@@ -99,7 +145,9 @@ import { useAgenticLayoutStyle } from "./style";
99
145
  * - 提供响应式布局适配
100
146
  * - 支持自定义宽度和高度
101
147
  * - 集成 Ant Design 主题系统
102
- */ export var AgenticLayout = function(param) {
148
+ */ var MIN_RIGHT_WIDTH = 400;
149
+ var MAX_RIGHT_WIDTH_RATIO = 0.7;
150
+ export var AgenticLayout = function(param) {
103
151
  var left = param.left, center = param.center, right = param.right, header = param.header, style = param.style, className = param.className, _param_leftWidth = param.leftWidth, leftWidth = _param_leftWidth === void 0 ? 256 : _param_leftWidth, _param_rightWidth = param.rightWidth, rightWidth = _param_rightWidth === void 0 ? 540 : _param_rightWidth;
104
152
  var getPrefixCls = useContext(ConfigProvider.ConfigContext).getPrefixCls;
105
153
  var prefixCls = getPrefixCls('agentic-layout');
@@ -109,6 +157,89 @@ import { useAgenticLayoutStyle } from "./style";
109
157
  var leftCollapsed = (_ref = (_header_leftCollapsed = header === null || header === void 0 ? void 0 : header.leftCollapsed) !== null && _header_leftCollapsed !== void 0 ? _header_leftCollapsed : header === null || header === void 0 ? void 0 : header.leftDefaultCollapsed) !== null && _ref !== void 0 ? _ref : false;
110
158
  var _header_rightCollapsed, _ref1;
111
159
  var rightCollapsed = (_ref1 = (_header_rightCollapsed = header === null || header === void 0 ? void 0 : header.rightCollapsed) !== null && _header_rightCollapsed !== void 0 ? _header_rightCollapsed : header === null || header === void 0 ? void 0 : header.rightDefaultCollapsed) !== null && _ref1 !== void 0 ? _ref1 : false;
160
+ // 右侧边栏宽度状态
161
+ var _useState = _sliced_to_array(useState(rightWidth), 2), currentRightWidth = _useState[0], setCurrentRightWidth = _useState[1];
162
+ var isResizingRef = useRef(false);
163
+ var resizeStartX = useRef(0);
164
+ var resizeStartWidth = useRef(rightWidth);
165
+ // 计算最大宽度(浏览器窗口的70%)
166
+ var getMaxRightWidth = useCallback(function() {
167
+ if (typeof window === 'undefined') return Infinity;
168
+ return window.innerWidth * MAX_RIGHT_WIDTH_RATIO;
169
+ }, []);
170
+ // 当 rightWidth prop 变化时更新状态
171
+ useEffect(function() {
172
+ setCurrentRightWidth(rightWidth);
173
+ }, [
174
+ rightWidth
175
+ ]);
176
+ // 监听窗口大小变化,确保右侧边栏宽度不超过最大限制
177
+ useEffect(function() {
178
+ var handleWindowResize = function() {
179
+ var maxWidth = getMaxRightWidth();
180
+ if (currentRightWidth > maxWidth) {
181
+ setCurrentRightWidth(maxWidth);
182
+ }
183
+ };
184
+ window.addEventListener('resize', handleWindowResize);
185
+ return function() {
186
+ window.removeEventListener('resize', handleWindowResize);
187
+ };
188
+ }, [
189
+ currentRightWidth,
190
+ getMaxRightWidth
191
+ ]);
192
+ // 处理拖拽过程
193
+ var handleResizeMove = useCallback(function(e) {
194
+ if (!isResizingRef.current) return;
195
+ // 向左拖拽(扩大右侧边栏)时 deltaX 为正,向右拖拽(缩小)时 deltaX 为负
196
+ var deltaX = resizeStartX.current - e.clientX;
197
+ var newWidth = resizeStartWidth.current + deltaX;
198
+ var maxWidth = getMaxRightWidth();
199
+ // 限制宽度范围
200
+ var clampedWidth = Math.max(MIN_RIGHT_WIDTH, Math.min(newWidth, maxWidth));
201
+ setCurrentRightWidth(clampedWidth);
202
+ }, [
203
+ getMaxRightWidth
204
+ ]);
205
+ // 处理拖拽结束
206
+ var handleResizeEnd = useCallback(function handleMouseUp() {
207
+ isResizingRef.current = false;
208
+ document.removeEventListener('mousemove', handleResizeMove);
209
+ document.removeEventListener('mouseup', handleMouseUp);
210
+ document.body.style.cursor = '';
211
+ document.body.style.userSelect = '';
212
+ }, [
213
+ handleResizeMove
214
+ ]);
215
+ // 处理拖拽开始
216
+ var handleResizeStart = useCallback(function(e) {
217
+ e.preventDefault();
218
+ e.stopPropagation();
219
+ isResizingRef.current = true;
220
+ resizeStartX.current = e.clientX;
221
+ resizeStartWidth.current = currentRightWidth;
222
+ document.addEventListener('mousemove', handleResizeMove);
223
+ document.addEventListener('mouseup', handleResizeEnd);
224
+ document.body.style.cursor = 'col-resize';
225
+ document.body.style.userSelect = 'none';
226
+ }, [
227
+ currentRightWidth,
228
+ handleResizeMove,
229
+ handleResizeEnd
230
+ ]);
231
+ // 清理事件监听器
232
+ useEffect(function() {
233
+ return function() {
234
+ document.removeEventListener('mousemove', handleResizeMove);
235
+ document.removeEventListener('mouseup', handleResizeEnd);
236
+ document.body.style.cursor = '';
237
+ document.body.style.userSelect = '';
238
+ };
239
+ }, [
240
+ handleResizeMove,
241
+ handleResizeEnd
242
+ ]);
112
243
  var _header_leftCollapsible, _header_rightCollapsible;
113
244
  return wrapSSR(/*#__PURE__*/ React.createElement("div", {
114
245
  className: "".concat(prefixCls, " ").concat(className || '', " ").concat(hashId),
@@ -132,7 +263,7 @@ import { useAgenticLayoutStyle } from "./style";
132
263
  className: "".concat(prefixCls, "-main ").concat(hashId),
133
264
  style: {
134
265
  flex: 1,
135
- minWidth: 0
266
+ minWidth: MIN_RIGHT_WIDTH
136
267
  }
137
268
  }, header && /*#__PURE__*/ React.createElement(LayoutHeader, _object_spread_props(_object_spread({}, header), {
138
269
  leftCollapsible: (_header_leftCollapsible = header.leftCollapsible) !== null && _header_leftCollapsible !== void 0 ? _header_leftCollapsible : !!left,
@@ -140,13 +271,23 @@ import { useAgenticLayoutStyle } from "./style";
140
271
  })), /*#__PURE__*/ React.createElement("div", {
141
272
  className: "".concat(prefixCls, "-main-content ").concat(hashId)
142
273
  }, center))), right && /*#__PURE__*/ React.createElement("div", {
274
+ className: "".concat(prefixCls, "-sidebar-wrapper-right ").concat(hashId),
275
+ style: {
276
+ display: 'flex',
277
+ alignItems: 'stretch',
278
+ height: '100%'
279
+ }
280
+ }, !rightCollapsed && /*#__PURE__*/ React.createElement("div", {
281
+ className: "".concat(prefixCls, "-resize-handle ").concat(prefixCls, "-resize-handle-right ").concat(hashId),
282
+ onMouseDown: handleResizeStart
283
+ }), /*#__PURE__*/ React.createElement("div", {
143
284
  className: "".concat(prefixCls, "-sidebar ").concat(prefixCls, "-sidebar-right ").concat(rightCollapsed ? "".concat(prefixCls, "-sidebar-right-collapsed") : '', " ").concat(hashId),
144
285
  style: {
145
- width: rightCollapsed ? 0 : rightWidth,
146
- minWidth: rightCollapsed ? 0 : rightWidth,
147
- maxWidth: rightCollapsed ? 0 : rightWidth
286
+ width: rightCollapsed ? 0 : currentRightWidth,
287
+ minWidth: rightCollapsed ? 0 : currentRightWidth,
288
+ maxWidth: rightCollapsed ? 0 : currentRightWidth
148
289
  }
149
290
  }, /*#__PURE__*/ React.createElement("div", {
150
291
  className: "".concat(prefixCls, "-sidebar-content ").concat(hashId)
151
- }, right))));
292
+ }, right)))));
152
293
  };
@@ -88,11 +88,15 @@ var genStyle = function(token) {
88
88
  minWidth: '0 !important',
89
89
  maxWidth: '0 !important',
90
90
  border: 'none !important'
91
+ }), // 右侧边栏包装器
92
+ _define_property(_obj, "&-sidebar-wrapper-right", {
93
+ display: 'flex',
94
+ alignItems: 'stretch',
95
+ height: '100%'
91
96
  }), // 右侧边栏特殊样式
92
97
  _define_property(_obj, "&-sidebar-right", {
93
98
  borderRight: 'none',
94
- height: '100%',
95
- marginLeft: 8
99
+ height: '100%'
96
100
  }), // 折叠状态样式
97
101
  _define_property(_obj, "&-sidebar-right-collapsed", _define_property({
98
102
  width: '0 !important',
@@ -103,7 +107,31 @@ var genStyle = function(token) {
103
107
  overflow: 'hidden'
104
108
  }, "".concat(token.componentCls, "-sidebar-content"), {
105
109
  display: 'none'
106
- })), // 侧边栏内容
110
+ })), // 拖拽手柄样式
111
+ _define_property(_obj, "&-resize-handle", {
112
+ width: '6px',
113
+ cursor: 'col-resize',
114
+ backgroundColor: 'transparent',
115
+ position: 'relative',
116
+ zIndex: 10,
117
+ flexShrink: 0,
118
+ marginLeft: '1px',
119
+ marginRight: '1px',
120
+ '&::before': {
121
+ content: '""',
122
+ position: 'absolute',
123
+ left: '50%',
124
+ top: 0,
125
+ bottom: 0,
126
+ width: '6px',
127
+ backgroundColor: 'transparent',
128
+ transform: 'translateX(-50%)',
129
+ transition: 'background-color 0.2s ease'
130
+ },
131
+ '&:hover::before': {
132
+ backgroundColor: 'var(--color-primary-9, #1d7afc)'
133
+ }
134
+ }), // 侧边栏内容
107
135
  _define_property(_obj, "&-sidebar-content", {
108
136
  flex: 1,
109
137
  display: 'flex',
@@ -209,7 +209,6 @@ function _ts_generator(thisArg, body) {
209
209
  }
210
210
  }
211
211
  import { memo, useContext } from "react";
212
- import { Loader } from "@sofa-design/icons";
213
212
  import { ConfigProvider, Flex } from "antd";
214
213
  import cx from "classnames";
215
214
  import React from "react";
@@ -232,10 +231,6 @@ export var runRender = function(render, props, defaultDom) {
232
231
  defaultDom
233
232
  ].concat(_to_consumable_array(rest))) : defaultDom;
234
233
  };
235
- var isTyping = function(originData) {
236
- var _originData_extra;
237
- return (originData === null || originData === void 0 ? void 0 : originData.isAborted) !== true && (originData === null || originData === void 0 ? void 0 : originData.isFinished) === false && (originData === null || originData === void 0 ? void 0 : (_originData_extra = originData.extra) === null || _originData_extra === void 0 ? void 0 : _originData_extra.isHistory) === undefined && (originData === null || originData === void 0 ? void 0 : originData.isFinished) !== undefined;
238
- };
239
234
  var isSameRoleAsPrevious = function(preMessage, originData) {
240
235
  if (!(preMessage === null || preMessage === void 0 ? void 0 : preMessage.role) || !(originData === null || originData === void 0 ? void 0 : originData.role)) return false;
241
236
  return preMessage.role === originData.role;
@@ -278,7 +273,6 @@ var shouldRenderBeforeContent = function(placement, role, thoughtChainConfig, ta
278
273
  var _ref = context || {}, compact = _ref.compact, standalone = _ref.standalone, locale = _ref.locale;
279
274
  var prefixClass = getPrefixCls('agentic');
280
275
  var _useStyle = useStyle(prefixClass), wrapSSR = _useStyle.wrapSSR, hashId = _useStyle.hashId;
281
- var typing = isTyping(originData);
282
276
  var preMessageSameRole = isSameRoleAsPrevious(preMessage, originData);
283
277
  var time = (originData === null || originData === void 0 ? void 0 : originData.createAt) || props.time;
284
278
  var avatar = (originData === null || originData === void 0 ? void 0 : originData.meta) || props.avatar;
@@ -411,11 +405,7 @@ var shouldRenderBeforeContent = function(placement, role, thoughtChainConfig, ta
411
405
  title: titleDom,
412
406
  header: /*#__PURE__*/ React.createElement("div", {
413
407
  className: cx("".concat(prefixClass, "-bubble-avatar-title"), "".concat(prefixClass, "-bubble-avatar-title-").concat(placement), "".concat(prefixClass, "-bubble-avatar-title-ai"), classNames === null || classNames === void 0 ? void 0 : classNames.bubbleAvatarTitleClassName, hashId)
414
- }, avatarDom, typing && /*#__PURE__*/ React.createElement(Loader, {
415
- style: {
416
- fontSize: 16
417
- }
418
- }), titleDom),
408
+ }, avatarDom, titleDom),
419
409
  extra: (props === null || props === void 0 ? void 0 : (_props_bubbleRenderConfig1 = props.bubbleRenderConfig) === null || _props_bubbleRenderConfig1 === void 0 ? void 0 : _props_bubbleRenderConfig1.extraRender) === false ? null : /*#__PURE__*/ React.createElement(BubbleExtra, {
420
410
  pure: true,
421
411
  style: (_props_styles = props.styles) === null || _props_styles === void 0 ? void 0 : _props_styles.bubbleListItemExtraStyle,
@@ -44,7 +44,7 @@ function _unsupported_iterable_to_array(o, minLen) {
44
44
  if (n === "Map" || n === "Set") return Array.from(n);
45
45
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
46
46
  }
47
- import { useState, useRef, useCallback } from "react";
47
+ import { useCallback, useRef, useState } from "react";
48
48
  /**
49
49
  * useRefState - 同时维护 state 和 ref 的 hook
50
50
  * @description 解决 setState 后立即读取 ref 得到旧值的问题
@@ -68,18 +68,20 @@ import { useStyle } from "./style";
68
68
  *
69
69
  * @returns {React.ReactElement} 渲染的聊天布局组件
70
70
  */ var ChatLayout = /*#__PURE__*/ forwardRef(function(param, ref) {
71
- var header = param.header, children = param.children, footer = param.footer, className = param.className, style = param.style;
71
+ var header = param.header, children = param.children, footer = param.footer, _param_footerHeight = param.footerHeight, footerHeight = _param_footerHeight === void 0 ? 90 : _param_footerHeight, _param_scrollBehavior = param.scrollBehavior, scrollBehavior = _param_scrollBehavior === void 0 ? 'smooth' : _param_scrollBehavior, className = param.className, style = param.style;
72
72
  var getPrefixCls = useContext(ConfigProvider.ConfigContext).getPrefixCls;
73
73
  var prefixCls = getPrefixCls('chat-layout');
74
74
  var _useStyle = useStyle(prefixCls), wrapSSR = _useStyle.wrapSSR, hashId = _useStyle.hashId;
75
- var containerRef = useAutoScroll({
75
+ var _useAutoScroll = useAutoScroll({
76
76
  SCROLL_TOLERANCE: 30,
77
77
  onResize: function() {},
78
- timeout: 200
79
- }).containerRef;
78
+ timeout: 200,
79
+ scrollBehavior: scrollBehavior
80
+ }), containerRef = _useAutoScroll.containerRef, scrollToBottom = _useAutoScroll.scrollToBottom;
80
81
  useImperativeHandle(ref, function() {
81
82
  return {
82
- scrollContainer: containerRef.current
83
+ scrollContainer: containerRef.current,
84
+ scrollToBottom: scrollToBottom
83
85
  };
84
86
  });
85
87
  return wrapSSR(/*#__PURE__*/ React.createElement("div", {
@@ -90,8 +92,16 @@ import { useStyle } from "./style";
90
92
  }, /*#__PURE__*/ React.createElement("div", {
91
93
  className: "".concat(prefixCls, "-content-scrollable ").concat(hashId),
92
94
  ref: containerRef
93
- }, children)), footer && /*#__PURE__*/ React.createElement("div", {
94
- className: "".concat(prefixCls, "-footer ").concat(hashId)
95
+ }, children, /*#__PURE__*/ React.createElement("div", {
96
+ style: {
97
+ height: footer ? footerHeight : 0,
98
+ width: '100%'
99
+ }
100
+ }))), footer && /*#__PURE__*/ React.createElement("div", {
101
+ className: "".concat(prefixCls, "-footer ").concat(hashId),
102
+ style: {
103
+ height: footerHeight
104
+ }
95
105
  }, footer)));
96
106
  });
97
107
  // 保持向后兼容,导出 ChatFlowHeader 作为 LayoutHeader 的别名
@@ -170,7 +170,6 @@ var genStyle = function(token) {
170
170
  paddingTop: 'var(--padding-2x)',
171
171
  paddingLeft: 'var(--padding-2x)',
172
172
  paddingRight: 'var(--padding-2x)',
173
- paddingBottom: '144px',
174
173
  '&::-webkit-scrollbar': {
175
174
  width: '6px'
176
175
  },
@@ -191,7 +190,10 @@ var genStyle = function(token) {
191
190
  }
192
191
  },
193
192
  '&-footer': {
194
- padding: 'var(--padding-4x)',
193
+ display: 'flex',
194
+ flexDirection: 'column',
195
+ alignItems: 'center',
196
+ justifyContent: 'center',
195
197
  background: 'linear-gradient(to bottom, #fff0 20%, var(--color-gray-bg-card-white) 70%)',
196
198
  width: '100%',
197
199
  position: 'absolute',
@@ -208,8 +210,7 @@ var genStyle = function(token) {
208
210
  '&-scrollable': {
209
211
  paddingTop: MOBILE_PADDING,
210
212
  paddingLeft: MOBILE_PADDING,
211
- paddingRight: MOBILE_PADDING,
212
- paddingBottom: '144px'
213
+ paddingRight: MOBILE_PADDING
213
214
  }
214
215
  },
215
216
  '&-footer': {
@@ -11,7 +11,12 @@ export interface ChatLayoutProps extends BaseStyleProps {
11
11
  children?: ReactNode;
12
12
  /** 底部区域的自定义内容 */
13
13
  footer?: ReactNode;
14
+ /** 底部区域的高度 */
15
+ footerHeight?: number;
16
+ /** 滚动行为 */
17
+ scrollBehavior?: 'smooth' | 'auto';
14
18
  }
15
19
  export interface ChatLayoutRef {
16
20
  scrollContainer: HTMLDivElement | null;
21
+ scrollToBottom: () => void;
17
22
  }