@baishuyun/ai-design 2.0.35 → 2.0.37

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @baishuyun/ai-design
2
2
 
3
+ ## 2.0.37
4
+
5
+ ### Patch Changes
6
+
7
+ - 移动端优化
8
+ - Updated dependencies
9
+ - @baishuyun/ai-feat-utils@2.0.33
10
+
11
+ ## 2.0.36
12
+
13
+ ### Patch Changes
14
+
15
+ - 消息过长折叠显示,附件图标完善
16
+ - Updated dependencies
17
+ - @baishuyun/ai-feat-utils@2.0.32
18
+ - @baishuyun/types@3.0.30
19
+
3
20
  ## 2.0.35
4
21
 
5
22
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baishuyun/ai-design",
3
- "version": "2.0.35",
3
+ "version": "2.0.37",
4
4
  "description": "AI 功能 UI 组件库 - 所有 AI 功能的 UI 表现唯一真相来源",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -60,8 +60,8 @@
60
60
  "tw-animate-css": "^1.4.0",
61
61
  "vaul": "^1.1.2",
62
62
  "zod": "^4.1.13",
63
- "@baishuyun/ai-feat-utils": "2.0.31",
64
- "@baishuyun/types": "3.0.29"
63
+ "@baishuyun/ai-feat-utils": "2.0.33",
64
+ "@baishuyun/types": "3.0.30"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "react": "^19.0.0",
@@ -83,8 +83,8 @@
83
83
  "typescript": "^5.5.0",
84
84
  "vite": "^5.1.4",
85
85
  "vite-plugin-dts": "^4.5.4",
86
+ "@baishuyun/types": "3.0.30",
86
87
  "@baishuyun/tailwind-config": "3.0.9",
87
- "@baishuyun/types": "3.0.29",
88
88
  "@baishuyun/typescript-config": "2.0.9"
89
89
  },
90
90
  "keywords": [],
@@ -1,5 +1,7 @@
1
1
  import { ComponentType } from 'react';
2
+ import { getIconUnicode } from '@baishuyun/ai-feat-utils';
2
3
  import { cn } from '../lib/utils';
4
+ import { FontIcon } from './font-icon';
3
5
  import { ImgMsgPart } from './img-part';
4
6
  import { XlsxIcon, CsvFileIcon, TxtFileIcon, UnknownFileIcon } from './bs-icons';
5
7
 
@@ -22,12 +24,45 @@ export interface AttachmentPartProps {
22
24
  onClick?: (part: FilePart) => void;
23
25
  }
24
26
 
25
- type FileIconComponent = ComponentType;
27
+ type FileIconComponent = ComponentType<{ color?: string }>;
26
28
 
27
- interface FileTypeConfig {
29
+ /**
30
+ * 字体图标方案:文件类型图标使用 baishu 主字体的 icon-bsy-* 字形
31
+ * (码位见 ai-feat-utils/iconfont.ts)。注意宿主的 .icon-bsy-form 类自带
32
+ * color 规则(PC 为 #0265ff),继承色会被覆盖,因此颜色必须通过
33
+ * FontIcon 的 color prop 以内联样式落到 <i> 上
34
+ */
35
+ const createFontFileIcon = (iconName: string): FileIconComponent => {
36
+ const FontFileIcon = ({ color }: { color?: string }) => (
37
+ <FontIcon
38
+ fontCls="icon-bsy-form"
39
+ code={getIconUnicode(iconName)}
40
+ color={color}
41
+ style={{ fontSize: 16, lineHeight: 1 }}
42
+ />
43
+ );
44
+ FontFileIcon.displayName = `FontFileIcon(${iconName})`;
45
+ return FontFileIcon;
46
+ };
47
+
48
+ const DocFileIcon = createFontFileIcon('bsy-doc');
49
+ const DocxFileIcon = createFontFileIcon('bsy-docx');
50
+ const PptFileIcon = createFontFileIcon('bsy-ppt');
51
+ const PptxFileIcon = createFontFileIcon('bsy-pptx');
52
+ const PdfFileIcon = createFontFileIcon('bsy-pdf');
53
+ const ZipFileIcon = createFontFileIcon('bsy-zip');
54
+ const RarFileIcon = createFontFileIcon('bsy-rar');
55
+ const Mp4FileIcon = createFontFileIcon('bsy-mp4');
56
+ const WebmFileIcon = createFontFileIcon('bsy-webm');
57
+ const MovFileIcon = createFontFileIcon('bsy-mov');
58
+ const AudioFileIcon = createFontFileIcon('bsy-ogg');
59
+
60
+ export interface FileTypeConfig {
28
61
  icon: FileIconComponent;
29
62
  /** Icon original size for scaling */
30
63
  iconSize: number;
64
+ /** Icon color (对齐 baishu BsyFileUpload 的 icon-bsy-* 配色),仅对字体图标生效 */
65
+ color?: string;
31
66
  }
32
67
 
33
68
  /** Map media types to icon configurations */
@@ -45,6 +80,44 @@ const FILE_TYPE_MAP: Record<string, FileTypeConfig> = {
45
80
  // Text files
46
81
  'text/plain': { icon: TxtFileIcon, iconSize: 16 },
47
82
  'application/octet-stream': { icon: TxtFileIcon, iconSize: 16 }, // treat as text for ts/js files
83
+
84
+ // Word files
85
+ 'application/msword': { icon: DocFileIcon, iconSize: 16, color: '#096dd9' },
86
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': {
87
+ icon: DocxFileIcon,
88
+ iconSize: 16,
89
+ color: '#096dd9',
90
+ },
91
+
92
+ // PowerPoint files
93
+ 'application/vnd.ms-powerpoint': { icon: PptFileIcon, iconSize: 16, color: '#d46b08' },
94
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation': {
95
+ icon: PptxFileIcon,
96
+ iconSize: 16,
97
+ color: '#08979c',
98
+ },
99
+
100
+ // PDF files
101
+ 'application/pdf': { icon: PdfFileIcon, iconSize: 16, color: '#d4380d' },
102
+
103
+ // Archive files
104
+ 'application/zip': { icon: ZipFileIcon, iconSize: 16, color: '#d46b08' },
105
+ 'application/x-zip-compressed': { icon: ZipFileIcon, iconSize: 16, color: '#d46b08' },
106
+ 'application/x-rar-compressed': { icon: RarFileIcon, iconSize: 16, color: '#389e0d' },
107
+ 'application/vnd.rar': { icon: RarFileIcon, iconSize: 16, color: '#389e0d' },
108
+ 'application/x-7z-compressed': { icon: ZipFileIcon, iconSize: 16, color: '#d46b08' },
109
+ 'application/gzip': { icon: ZipFileIcon, iconSize: 16, color: '#d46b08' },
110
+
111
+ // Video files
112
+ 'video/mp4': { icon: Mp4FileIcon, iconSize: 16, color: '#1d39c4' },
113
+ 'video/webm': { icon: WebmFileIcon, iconSize: 16, color: '#d46b08' },
114
+ 'video/quicktime': { icon: MovFileIcon, iconSize: 16, color: '#1d39c4' }, // mov
115
+
116
+ // Audio files
117
+ 'audio/ogg': { icon: AudioFileIcon, iconSize: 16, color: '#d4380d' },
118
+ 'audio/mpeg': { icon: AudioFileIcon, iconSize: 16, color: '#d4380d' }, // mp3
119
+ 'audio/wav': { icon: AudioFileIcon, iconSize: 16, color: '#d4380d' },
120
+ 'audio/x-wav': { icon: AudioFileIcon, iconSize: 16, color: '#d4380d' },
48
121
  };
49
122
 
50
123
  const DEFAULT_FILE_CONFIG: FileTypeConfig = {
@@ -53,17 +126,25 @@ const DEFAULT_FILE_CONFIG: FileTypeConfig = {
53
126
  };
54
127
 
55
128
  /** Check if media type is an image */
56
- const isImageType = (mediaType?: string): boolean => {
129
+ export const isImageType = (mediaType?: string): boolean => {
57
130
  return Boolean(mediaType?.startsWith('image/'));
58
131
  };
59
132
 
60
133
  /** Get file config based on media type and file extension */
61
- const getFileConfig = (mediaType?: string, fileName?: string): FileTypeConfig => {
134
+ export const getFileConfig = (mediaType?: string, fileName?: string): FileTypeConfig => {
62
135
  // Check media type first
63
136
  if (mediaType && FILE_TYPE_MAP[mediaType]) {
64
137
  return FILE_TYPE_MAP[mediaType];
65
138
  }
66
139
 
140
+ // Prefix match for video/audio (covers mkv/avi/flac/m4a etc.)
141
+ if (mediaType?.startsWith('video/')) {
142
+ return FILE_TYPE_MAP['video/mp4'];
143
+ }
144
+ if (mediaType?.startsWith('audio/')) {
145
+ return FILE_TYPE_MAP['audio/ogg'];
146
+ }
147
+
67
148
  // Fallback to file extension
68
149
  if (fileName) {
69
150
  const ext = fileName.split('.').pop()?.toLowerCase();
@@ -81,6 +162,38 @@ const getFileConfig = (mediaType?: string, fileName?: string): FileTypeConfig =>
81
162
  case 'json':
82
163
  case 'md':
83
164
  return FILE_TYPE_MAP['text/plain'];
165
+ case 'doc':
166
+ return FILE_TYPE_MAP['application/msword'];
167
+ case 'docx':
168
+ return FILE_TYPE_MAP['application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
169
+ case 'ppt':
170
+ return FILE_TYPE_MAP['application/vnd.ms-powerpoint'];
171
+ case 'pptx':
172
+ return FILE_TYPE_MAP['application/vnd.openxmlformats-officedocument.presentationml.presentation'];
173
+ case 'pdf':
174
+ return FILE_TYPE_MAP['application/pdf'];
175
+ case 'zip':
176
+ case '7z':
177
+ case 'gz':
178
+ case 'tar':
179
+ return FILE_TYPE_MAP['application/zip'];
180
+ case 'rar':
181
+ return FILE_TYPE_MAP['application/x-rar-compressed'];
182
+ case 'mp4':
183
+ case 'mkv':
184
+ case 'avi':
185
+ return FILE_TYPE_MAP['video/mp4'];
186
+ case 'webm':
187
+ return FILE_TYPE_MAP['video/webm'];
188
+ case 'mov':
189
+ return FILE_TYPE_MAP['video/quicktime'];
190
+ case 'ogg':
191
+ case 'mp3':
192
+ case 'wav':
193
+ case 'flac':
194
+ case 'aac':
195
+ case 'm4a':
196
+ return FILE_TYPE_MAP['audio/ogg'];
84
197
  }
85
198
  }
86
199
 
@@ -100,12 +213,14 @@ const FileMsgPart = ({
100
213
  fileName,
101
214
  icon: Icon,
102
215
  iconSize,
216
+ color,
103
217
  className,
104
218
  size = 102,
105
219
  }: {
106
220
  fileName?: string;
107
221
  icon: FileIconComponent;
108
222
  iconSize: number;
223
+ color?: string;
109
224
  className?: string;
110
225
  size?: number;
111
226
  }) => {
@@ -128,6 +243,7 @@ const FileMsgPart = ({
128
243
  style={{
129
244
  width: scaledIconSize,
130
245
  height: scaledIconSize,
246
+ color,
131
247
  }}
132
248
  >
133
249
  <div
@@ -136,7 +252,7 @@ const FileMsgPart = ({
136
252
  transformOrigin: 'center',
137
253
  }}
138
254
  >
139
- <Icon />
255
+ <Icon color={color} />
140
256
  </div>
141
257
  </div>
142
258
  {hasFileName && (
@@ -162,7 +278,7 @@ export const AttachmentPart = ({ part, className, size = 102, iconOnly, onClick
162
278
  }
163
279
 
164
280
  // Render file icon for other types
165
- const { icon, iconSize } = getFileConfig(mediaType, name);
281
+ const { icon, iconSize, color } = getFileConfig(mediaType, name);
166
282
  const displayName = iconOnly ? undefined : getDisplayFileName(name);
167
283
 
168
284
  return (
@@ -171,6 +287,7 @@ export const AttachmentPart = ({ part, className, size = 102, iconOnly, onClick
171
287
  fileName={displayName}
172
288
  icon={icon}
173
289
  iconSize={iconSize}
290
+ color={color}
174
291
  className={className}
175
292
  size={size}
176
293
  />
@@ -1,8 +1,9 @@
1
1
  import { cn } from '../lib/utils';
2
2
  import { transCls } from '../const/ui';
3
- import { useRef, useState, useEffect, useCallback, ComponentType } from 'react';
4
- import { RemoveCircleIcon, XlsxIcon, CsvFileIcon, TxtFileIcon, UnknownFileIcon } from './bs-icons';
3
+ import { useRef, useState, useEffect, useCallback } from 'react';
4
+ import { RemoveCircleIcon } from './bs-icons';
5
5
  import { LoaderIcon } from './ui/icons';
6
+ import { getFileConfig, isImageType } from './attachment-part';
6
7
 
7
8
  export interface AttachmentItem {
8
9
  id: string;
@@ -22,59 +23,6 @@ export interface AttachmentsPreviewerProps {
22
23
  onImageRemove?: (attachment: AttachmentItem, index: number) => void;
23
24
  }
24
25
 
25
- type FileIconComponent = ComponentType;
26
-
27
- interface FileTypeConfig {
28
- icon: FileIconComponent;
29
- /** Icon original size for scaling */
30
- iconSize: number;
31
- }
32
-
33
- const FILE_TYPE_MAP: Record<string, FileTypeConfig> = {
34
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': {
35
- icon: XlsxIcon,
36
- iconSize: 52,
37
- },
38
- 'application/vnd.ms-excel': { icon: XlsxIcon, iconSize: 52 },
39
- 'text/csv': { icon: CsvFileIcon, iconSize: 16 },
40
- 'text/plain': { icon: TxtFileIcon, iconSize: 16 },
41
- 'application/octet-stream': { icon: TxtFileIcon, iconSize: 16 },
42
- };
43
-
44
- const DEFAULT_FILE_CONFIG: FileTypeConfig = {
45
- icon: UnknownFileIcon,
46
- iconSize: 16,
47
- };
48
-
49
- const isImageType = (mediaType?: string): boolean => Boolean(mediaType?.startsWith('image/'));
50
-
51
- const getFileConfig = (mediaType?: string, fileName?: string): FileTypeConfig => {
52
- if (mediaType && FILE_TYPE_MAP[mediaType]) {
53
- return FILE_TYPE_MAP[mediaType];
54
- }
55
-
56
- if (fileName) {
57
- const ext = fileName.split('.').pop()?.toLowerCase();
58
- switch (ext) {
59
- case 'xlsx':
60
- case 'xls':
61
- return FILE_TYPE_MAP['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
62
- case 'csv':
63
- return FILE_TYPE_MAP['text/csv'];
64
- case 'txt':
65
- case 'ts':
66
- case 'tsx':
67
- case 'js':
68
- case 'jsx':
69
- case 'json':
70
- case 'md':
71
- return FILE_TYPE_MAP['text/plain'];
72
- }
73
- }
74
-
75
- return DEFAULT_FILE_CONFIG;
76
- };
77
-
78
26
  const ChevronRightIcon = () => (
79
27
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
80
28
  <path
@@ -231,7 +179,7 @@ export const AttachmentsPreviewer = ({
231
179
  >
232
180
  {attachments.map((attachment, index) => {
233
181
  const isImage = isImageType(attachment.contentType);
234
- const { icon: Icon, iconSize } = getFileConfig(attachment.contentType, attachment.alt);
182
+ const { icon: Icon, iconSize, color } = getFileConfig(attachment.contentType, attachment.alt);
235
183
  const scaledIconSize = (52 / 102) * imageSize;
236
184
  const iconScale = scaledIconSize / iconSize;
237
185
 
@@ -255,7 +203,7 @@ export const AttachmentsPreviewer = ({
255
203
  <div className="absolute inset-0 flex h-full w-full items-center justify-center rounded-lg bg-[#EFF0F6]">
256
204
  <div
257
205
  className="shrink-0 flex items-center justify-center"
258
- style={{ width: scaledIconSize, height: scaledIconSize }}
206
+ style={{ width: scaledIconSize, height: scaledIconSize, color }}
259
207
  >
260
208
  <div
261
209
  style={{
@@ -263,7 +211,7 @@ export const AttachmentsPreviewer = ({
263
211
  transformOrigin: 'center',
264
212
  }}
265
213
  >
266
- <Icon />
214
+ <Icon color={color} />
267
215
  </div>
268
216
  </div>
269
217
  </div>
@@ -1,5 +1,3 @@
1
- import { transCls } from '../const/ui';
2
- import { cn } from '../lib/utils';
3
1
  // import { FontIcon } from './font-icon';
4
2
 
5
3
  export const DockIcon = () => (
@@ -2,6 +2,7 @@ import { ReactNode, useState } from 'react';
2
2
  import { cn } from '../lib/utils';
3
3
  import { transCls } from '../const/ui';
4
4
  import { AnalysisIcon, ChevronIcon } from './bs-icons';
5
+ import classNames from 'classnames';
5
6
 
6
7
  export interface CollapsibleTxtMsgProps {
7
8
  title: string;
@@ -10,11 +11,14 @@ export interface CollapsibleTxtMsgProps {
10
11
  defaultOpen?: boolean;
11
12
  children?: ReactNode;
12
13
 
14
+ ghost?: boolean;
15
+
13
16
  disableExpand?: boolean;
14
17
  }
15
18
 
16
19
  export const CollapsibleTxtMsg = ({
17
20
  title,
21
+ ghost,
18
22
  content,
19
23
  icon,
20
24
  disableExpand,
@@ -23,8 +27,16 @@ export const CollapsibleTxtMsg = ({
23
27
  }: CollapsibleTxtMsgProps) => {
24
28
  const [isOpen, setIsOpen] = useState(defaultOpen);
25
29
 
30
+ const cls = classNames({
31
+ 'bg-[#fafafa] border border-[#e0e0e0] border-solid p-2.5': !ghost
32
+ })
33
+
34
+ const isGhostOpen = isOpen && ghost;
35
+
36
+ const t = isGhostOpen ? '' : title;
37
+
26
38
  return (
27
- <div className="bg-[#fafafa] border border-[#e0e0e0] border-solid flex flex-col gap-2.5 p-2.5 rounded-lg w-full">
39
+ <div className={classNames("flex flex-col gap-2.5 rounded-lg w-full", cls)}>
28
40
  <div
29
41
  className={cn('flex items-center justify-between w-full', {
30
42
  'cursor-pointer': !disableExpand,
@@ -37,7 +49,7 @@ export const CollapsibleTxtMsg = ({
37
49
  >
38
50
  <div className="flex gap-2.5 items-center">
39
51
  <div className="w-4 h-4 shrink-0 flex items-center">{icon || <AnalysisIcon />}</div>
40
- <p className="text-[#666] text-[14px] leading-normal">{title}</p>
52
+ <p className="text-[#666] text-[14px] leading-normal">{t}</p>
41
53
  </div>
42
54
  <button
43
55
  onClick={() => {
@@ -20,12 +20,14 @@ export const FontIcon = ({
20
20
  code,
21
21
  name,
22
22
  className,
23
+ fontCls= 'sdk-icon',
23
24
  style,
24
25
  color,
25
26
  }: {
26
27
  code?: string;
27
28
  name?: number;
28
29
  className?: string;
30
+ fontCls?: string;
29
31
  style?: React.CSSProperties;
30
32
  color?: string;
31
33
  }) => {
@@ -36,7 +38,7 @@ export const FontIcon = ({
36
38
  if (code) {
37
39
  return (
38
40
  <i
39
- className={`sdk-icon ${className || ''}`}
41
+ className={`${fontCls} ${className || ''}`}
40
42
  style={{ ...style, color }}
41
43
  dangerouslySetInnerHTML={{ __html: code }}
42
44
  />
@@ -58,9 +58,12 @@ function DrawerContent({
58
58
  className,
59
59
  children,
60
60
  container: containerProp,
61
+ hideOverlay = false,
61
62
  ...props
62
63
  }: React.ComponentProps<typeof DrawerPrimitive.Content> & {
63
64
  container?: HTMLElement | null;
65
+ /** 全屏等场景下头部需保持可交互时,可隐藏遮罩 */
66
+ hideOverlay?: boolean;
64
67
  }) {
65
68
  const [autoContainer, setAutoContainer] = React.useState<HTMLElement | null>(null);
66
69
 
@@ -102,7 +105,7 @@ function DrawerContent({
102
105
  <span ref={setDetectorRef} style={{ display: 'none' }} aria-hidden />
103
106
  )}
104
107
  <DrawerPortal container={effectiveContainer ?? undefined}>
105
- <DrawerOverlay />
108
+ {!hideOverlay && <DrawerOverlay />}
106
109
  <DrawerPrimitive.Content
107
110
  data-slot="drawer-content"
108
111
  className={cn(
@@ -20,7 +20,7 @@ const PopoverContent = React.forwardRef<
20
20
  PopoverContentProps
21
21
  >(
22
22
  (
23
- { className, align = 'start', sideOffset = 4, portalContainer, style, onWheel, ...props },
23
+ { className, align = 'start', sideOffset = 4, portalContainer, style, onWheel, onOpenAutoFocus, ...props },
24
24
  ref
25
25
  ) => {
26
26
  const handleWheel = portalContainer
@@ -45,6 +45,12 @@ const PopoverContent = React.forwardRef<
45
45
  }
46
46
  : onWheel;
47
47
 
48
+ // 默认阻止 Radix 打开浮层时自动聚焦内部第一个可聚焦元素(通常是搜索框),
49
+ // 移动端会因此唤起软键盘,不是期望的交互;调用方仍可显式传 onOpenAutoFocus 覆盖
50
+ const handleOpenAutoFocus = onOpenAutoFocus ?? ((event: Event) => {
51
+ event.preventDefault();
52
+ });
53
+
48
54
  return (
49
55
  <PopoverPrimitive.Portal container={portalContainer ?? undefined}>
50
56
  <PopoverPrimitive.Content
@@ -52,6 +58,7 @@ const PopoverContent = React.forwardRef<
52
58
  align={align}
53
59
  sideOffset={sideOffset}
54
60
  onWheel={handleWheel}
61
+ onOpenAutoFocus={handleOpenAutoFocus}
55
62
  className={cn(
56
63
  'z-50 w-60 rounded-[8px] bg-white p-1 text-[#121111] shadow-[0px_6px_16px_rgba(0,0,0,0.06)] outline-none',
57
64
  'data-[state=open]:animate-in data-[state=closed]:animate-out',
@@ -1,9 +1,31 @@
1
+ import { TextIcon } from "./bs-icons";
2
+ import { CollapsibleTxtMsg } from "./collapsible-txt-msg";
3
+
1
4
  export interface UserTextMsgBubbleProps {
2
5
  text?: string;
3
6
  children?: string;
4
7
  }
5
8
 
6
9
  export const UserTextMsgBubble = ({ text, children }: UserTextMsgBubbleProps) => {
10
+ const content = (text || children) as string;
11
+
12
+ if (typeof content !== 'string') {
13
+ return (
14
+ <div
15
+ className="px-2.5 py-[7px] text-[#0265FF] text-[14px] w-fit"
16
+ style={{
17
+ borderRadius: `10px 0 10px 10px`,
18
+ wordWrap: 'break-word',
19
+ background: `linear-gradient(180deg, #DBE9FF 0%, #E9FFFD 100%)`,
20
+ }}
21
+ >
22
+ {content}
23
+ </div>
24
+ )
25
+ }
26
+
27
+ const isTooLong = content.length > 200;
28
+ const summary = `${content?.slice(0, 10)}...`;
7
29
  return (
8
30
  <div
9
31
  className="px-2.5 py-[7px] text-[#0265FF] text-[14px] w-fit"
@@ -13,7 +35,13 @@ export const UserTextMsgBubble = ({ text, children }: UserTextMsgBubbleProps) =>
13
35
  background: `linear-gradient(180deg, #DBE9FF 0%, #E9FFFD 100%)`,
14
36
  }}
15
37
  >
16
- {text || children}
38
+ {isTooLong ? (
39
+ <CollapsibleTxtMsg
40
+ icon={<TextIcon />}
41
+ ghost
42
+ title={summary}
43
+ >{content}</CollapsibleTxtMsg>
44
+ ) : content}
17
45
  </div>
18
46
  );
19
47
  };