@agentscope-ai/chat 1.1.53 → 1.1.54-beta.1773217735669

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.
@@ -2,16 +2,14 @@ import classnames from 'classnames';
2
2
  import React from 'react';
3
3
  import type { Attachment } from '..';
4
4
  import { AttachmentContext } from '../context';
5
- import { previewImage } from '../util';
6
- import AudioIcon from './AudioIcon';
7
- import Progress from './Progress';
8
- import VideoIcon from './VideoIcon';
9
5
  import Style from '../style/fileCard';
10
6
  import { useProviderContext } from '@agentscope-ai/chat';
11
7
  import { SparkFalseLine } from '@agentscope-ai/icons';
8
+ import ImageCard from './ImageCard';
9
+ import type { ImageCardProps } from './ImageCard';
12
10
 
13
11
 
14
- export interface FileListCardProps {
12
+ export interface FileListCardProps extends Pick<ImageCardProps, 'onReplace'> {
15
13
  /**
16
14
  * @description 自定义CSS类名前缀,用于样式隔离和主题定制
17
15
  * @descriptionEn Custom CSS class name prefix for style isolation and theme customization
@@ -42,7 +40,6 @@ export interface FileListCardProps {
42
40
  * @descriptionEn Render type, currently only supports default render mode
43
41
  */
44
42
  renderType?: 'default',
45
-
46
43
  }
47
44
 
48
45
  const EMPTY = '\u00A0';
@@ -126,7 +123,7 @@ function getSize(size: number) {
126
123
 
127
124
  function FileListCard(props: FileListCardProps, ref: React.Ref<HTMLDivElement>) {
128
125
  const { getPrefixCls } = useProviderContext();
129
- const { item, onRemove, className, style } = props;
126
+ const { item, onRemove, onReplace, className, style } = props;
130
127
  const context = React.useContext(AttachmentContext);
131
128
  const { disabled } = context || {};
132
129
  const { name, size, percent, status = 'done', description } = item;
@@ -141,7 +138,23 @@ function FileListCard(props: FileListCardProps, ref: React.Ref<HTMLDivElement>)
141
138
 
142
139
  const isImg = React.useMemo(() => matchExt(nameSuffix, IMG_EXTS), [nameSuffix]);
143
140
 
144
- const desc = React.useMemo(() => {
141
+ const renderType = props.renderType || 'default';
142
+ const isImgPreview = isImg && (item.originFileObj || item.thumbUrl || item.url) && renderType === 'default';
143
+
144
+ if (isImgPreview) {
145
+ return (
146
+ <ImageCard
147
+ ref={ref}
148
+ item={item}
149
+ onRemove={onRemove}
150
+ onReplace={onReplace}
151
+ className={className}
152
+ style={style}
153
+ />
154
+ );
155
+ }
156
+
157
+ const desc = (() => {
145
158
  if (description) {
146
159
  return description;
147
160
  }
@@ -155,9 +168,9 @@ function FileListCard(props: FileListCardProps, ref: React.Ref<HTMLDivElement>)
155
168
  }
156
169
 
157
170
  return size ? getSize(size) : EMPTY;
158
- }, [status, percent]);
171
+ })();
159
172
 
160
- const [icon, iconColor] = React.useMemo(() => {
173
+ const [icon, iconColor] = (() => {
161
174
  for (const { ext, icon, color } of PRESET_FILE_ICONS) {
162
175
  if (matchExt(nameSuffix, ext)) {
163
176
  return [icon, color];
@@ -165,57 +178,25 @@ function FileListCard(props: FileListCardProps, ref: React.Ref<HTMLDivElement>)
165
178
  }
166
179
 
167
180
  return [<IconImage url="https://gw.alicdn.com/imgextra/i1/O1CN01K7jgEj1sywWTkPSGY_!!6000000005836-55-tps-40-40.svg" key="defaultIcon" />, DEFAULT_ICON_COLOR];
168
- }, [nameSuffix]);
169
-
170
- const [previewImg, setPreviewImg] = React.useState<string>();
171
-
172
- React.useEffect(() => {
173
- if (item.originFileObj) {
174
- let synced = true;
175
- previewImage(item.originFileObj).then((url) => {
176
- if (synced) {
177
- setPreviewImg(url);
178
- }
179
- });
180
-
181
- return () => {
182
- synced = false;
183
- };
184
- }
185
- setPreviewImg(undefined);
186
- }, [item.originFileObj]);
187
-
188
- let content: React.ReactNode = null;
189
- const previewUrl = item.thumbUrl || item.url || previewImg;
190
- const renderType = props.renderType || 'default';
191
- const isImgPreview = isImg && (item.originFileObj || previewUrl) && renderType === 'default';
192
-
193
- if (isImgPreview) {
194
- content = (
195
- <>
196
- {
197
- previewUrl && (
198
- <img alt="preview" src={previewUrl} />
199
- )
200
- }
201
-
202
- {status !== 'done' && (
203
- <div className={`${cardCls}-img-mask`}>
204
- {status === 'uploading' && percent !== undefined && (
205
- <Progress percent={percent} prefixCls={cardCls} />
206
- )}
207
- {status === 'error' && (
208
- <div className={`${cardCls}-desc`}>
209
- <div className={`${cardCls}-ellipsis-prefix`}>{desc}</div>
210
- </div>
211
- )}
212
- </div>
181
+ })();
182
+
183
+ return (
184
+ <>
185
+ <Style />
186
+ <div
187
+ className={classnames(
188
+ cardCls,
189
+ {
190
+ [`${cardCls}-status-${status}`]: status,
191
+ [`${cardCls}-type-overview`]: true,
192
+ [`${cardCls}-type-${renderType}`]: true,
193
+ [`${cardCls}-hoverable`]: !disabled && onRemove,
194
+ },
195
+ className,
213
196
  )}
214
- </>
215
- );
216
- } else {
217
- content = (
218
- <>
197
+ style={style}
198
+ ref={ref}
199
+ >
219
200
  <div className={`${cardCls}-icon`} style={{ color: iconColor }}>
220
201
  {icon}
221
202
  </div>
@@ -227,44 +208,23 @@ function FileListCard(props: FileListCardProps, ref: React.Ref<HTMLDivElement>)
227
208
  <div className={`${cardCls}-ellipsis-prefix`}>{desc}</div>
228
209
  </div>
229
210
  </div>
230
- </>
231
- );
232
- }
233
-
234
- return <>
235
- <Style />
236
- <div
237
- className={classnames(
238
- cardCls,
239
- {
240
- [`${cardCls}-status-${status}`]: status,
241
- [`${cardCls}-type-preview`]: isImgPreview,
242
- [`${cardCls}-type-overview`]: !isImgPreview,
243
- [`${cardCls}-type-${renderType}`]: true,
244
- [`${cardCls}-hoverable`]: !disabled && onRemove,
245
- },
246
- className,
247
- )}
248
- style={style}
249
- ref={ref}
250
- >
251
- {content}
252
-
253
- <button
254
- style={{
255
- opacity: !disabled && onRemove ? 1 : 0,
256
- }}
257
- className={`${cardCls}-remove`}
258
- onClick={() => {
259
- if (!disabled && onRemove) {
260
- onRemove(item);
261
- }
262
- }}
263
- >
264
- <SparkFalseLine />
265
211
 
266
- </button>
267
- </div></>
212
+ <button
213
+ style={{
214
+ opacity: !disabled && onRemove ? 1 : 0,
215
+ }}
216
+ className={`${cardCls}-remove`}
217
+ onClick={() => {
218
+ if (!disabled && onRemove) {
219
+ onRemove(item);
220
+ }
221
+ }}
222
+ >
223
+ <SparkFalseLine />
224
+ </button>
225
+ </div>
226
+ </>
227
+ );
268
228
  }
269
229
 
270
230
  export default React.forwardRef(FileListCard);
@@ -0,0 +1,197 @@
1
+ import classnames from 'classnames';
2
+ import React from 'react';
3
+ import { Image } from 'antd';
4
+ import type { Attachment } from '..';
5
+ import { AttachmentContext } from '../context';
6
+ import { previewImage } from '../util';
7
+ import Progress from './Progress';
8
+ import Style from '../style/fileCard';
9
+ import { useProviderContext } from '@agentscope-ai/chat';
10
+ import { SparkFalseLine, SparkVisibleLine, SparkRefreshLine, SparkReplaceLine } from '@agentscope-ai/icons';
11
+
12
+ export interface ImageCardProps {
13
+ /**
14
+ * @description 文件附件数据对象,包含文件的基本信息
15
+ * @descriptionEn File attachment data object containing basic file information
16
+ */
17
+ item: Attachment;
18
+ /**
19
+ * @description 文件移除时的回调函数,用于处理文件删除操作
20
+ * @descriptionEn Callback function when file is removed for handling file deletion operations
21
+ */
22
+ onRemove?: (item: Attachment) => void;
23
+ /**
24
+ * @description 替换当前图片的回调,传入原始附件和新选择的文件
25
+ * @descriptionEn Callback to replace current image, receives the original attachment and newly selected file
26
+ */
27
+ onReplace?: (oldItem: Attachment, file: File) => void;
28
+ /**
29
+ * @description 组件的CSS类名
30
+ * @descriptionEn CSS class name for the component
31
+ */
32
+ className?: string;
33
+ /**
34
+ * @description 组件的内联样式对象
35
+ * @descriptionEn Inline style object for the component
36
+ */
37
+ style?: React.CSSProperties;
38
+ }
39
+
40
+ const EMPTY = '\u00A0';
41
+
42
+ const IMG_ACCEPT = 'image/png,image/jpeg,image/jpg,image/gif,image/bmp,image/webp,image/svg+xml';
43
+
44
+ function ImageCard(props: ImageCardProps, ref: React.Ref<HTMLDivElement>) {
45
+ const { getPrefixCls } = useProviderContext();
46
+ const { item, onRemove, onReplace, className, style } = props;
47
+ const context = React.useContext(AttachmentContext);
48
+ const { disabled } = context || {};
49
+ const { percent, status = 'done', description } = item;
50
+ const prefixCls = getPrefixCls('attachment');
51
+ const cardCls = `${prefixCls}-list-card`;
52
+
53
+ const [previewVisible, setPreviewVisible] = React.useState(false);
54
+ const fileInputRef = React.useRef<HTMLInputElement>(null);
55
+
56
+ const previewConfig = React.useMemo(() => ({
57
+ visible: previewVisible,
58
+ onVisibleChange: setPreviewVisible,
59
+ }), [previewVisible]);
60
+
61
+ const desc = React.useMemo(() => {
62
+ if (description) {
63
+ return description;
64
+ }
65
+
66
+ if (status === 'uploading') {
67
+ return `${percent || 0}%`;
68
+ }
69
+
70
+ if (status === 'error') {
71
+ return item.response || EMPTY;
72
+ }
73
+
74
+ return EMPTY;
75
+ }, [description, status, percent, item.response]);
76
+
77
+ const [previewImg, setPreviewImg] = React.useState<string>();
78
+
79
+ React.useEffect(() => {
80
+ if (item.originFileObj) {
81
+ let synced = true;
82
+ previewImage(item.originFileObj).then((url) => {
83
+ if (synced) {
84
+ setPreviewImg(url);
85
+ }
86
+ });
87
+
88
+ return () => {
89
+ synced = false;
90
+ };
91
+ }
92
+ setPreviewImg(undefined);
93
+ }, [item.originFileObj]);
94
+
95
+ const previewUrl = item.thumbUrl || item.url || previewImg;
96
+
97
+ const handleRefreshClick = (e: React.MouseEvent) => {
98
+ e.stopPropagation();
99
+ fileInputRef.current?.click();
100
+ };
101
+
102
+ const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
103
+ const file = e.target.files?.[0];
104
+ if (file && onReplace) {
105
+ onReplace(item, file);
106
+ }
107
+ if (fileInputRef.current) {
108
+ fileInputRef.current.value = '';
109
+ }
110
+ };
111
+
112
+ return (
113
+ <>
114
+ <Style />
115
+ <div
116
+ className={classnames(
117
+ cardCls,
118
+ {
119
+ [`${cardCls}-status-${status}`]: status,
120
+ [`${cardCls}-type-preview`]: true,
121
+ [`${cardCls}-hoverable`]: !disabled && onRemove,
122
+ },
123
+ className,
124
+ )}
125
+ style={style}
126
+ ref={ref}
127
+ >
128
+ {previewUrl && <img alt="preview" src={previewUrl} />}
129
+
130
+ <Image
131
+ src={previewUrl}
132
+ style={{ display: 'none' }}
133
+ preview={previewConfig}
134
+ />
135
+
136
+ {status !== 'done' && (
137
+ <div className={`${cardCls}-img-mask`}>
138
+ {status === 'uploading' && percent !== undefined && (
139
+ <Progress percent={percent} prefixCls={cardCls} />
140
+ )}
141
+ {status === 'error' && (
142
+ <div className={`${cardCls}-desc`}>
143
+ <div className={`${cardCls}-ellipsis-prefix`}>{desc}</div>
144
+ </div>
145
+ )}
146
+ </div>
147
+ )}
148
+
149
+ {status === 'done' && (
150
+ <div className={`${cardCls}-img-hover-mask`}>
151
+ <button
152
+ className={`${cardCls}-img-action`}
153
+ onClick={(e) => {
154
+ e.stopPropagation();
155
+ setPreviewVisible(true);
156
+ }}
157
+ >
158
+ <SparkVisibleLine />
159
+ </button>
160
+ {onReplace && (
161
+ <button
162
+ className={`${cardCls}-img-action`}
163
+ onClick={handleRefreshClick}
164
+ >
165
+ <SparkReplaceLine />
166
+ </button>
167
+ )}
168
+ </div>
169
+ )}
170
+
171
+ <input
172
+ ref={fileInputRef}
173
+ type="file"
174
+ accept={IMG_ACCEPT}
175
+ style={{ display: 'none' }}
176
+ onChange={handleFileChange}
177
+ />
178
+
179
+ <button
180
+ style={{
181
+ opacity: !disabled && onRemove ? 1 : 0,
182
+ }}
183
+ className={`${cardCls}-remove`}
184
+ onClick={() => {
185
+ if (!disabled && onRemove) {
186
+ onRemove(item);
187
+ }
188
+ }}
189
+ >
190
+ <SparkFalseLine />
191
+ </button>
192
+ </div>
193
+ </>
194
+ );
195
+ }
196
+
197
+ export default React.forwardRef(ImageCard);
@@ -22,6 +22,11 @@ export interface FileListProps {
22
22
  * @descriptionEn Callback function when file is removed for handling file deletion operations
23
23
  */
24
24
  onRemove: (item: Attachment) => void;
25
+ /**
26
+ * @description 替换图片文件的回调,传入原始附件和新选择的文件
27
+ * @descriptionEn Callback to replace an image file, receives the original attachment and newly selected file
28
+ */
29
+ onReplace?: (oldItem: Attachment, file: File) => void;
25
30
  /**
26
31
  * @description 文件列表的溢出处理方式,影响滚动和布局行为
27
32
  * @descriptionEn Overflow handling method for file list, affects scrolling and layout behavior
@@ -68,6 +73,7 @@ export default function FileList(props: FileListProps) {
68
73
  prefixCls,
69
74
  items,
70
75
  onRemove,
76
+ onReplace,
71
77
  overflow,
72
78
  listClassName,
73
79
  listStyle,
@@ -167,6 +173,7 @@ export default function FileList(props: FileListProps) {
167
173
  prefixCls={prefixCls}
168
174
  item={item}
169
175
  onRemove={onRemove}
176
+ onReplace={onReplace}
170
177
  className={classnames(motionCls, itemClassName)}
171
178
  style={{
172
179
  ...motionStyle,
@@ -7,6 +7,7 @@ import { useEvent, useMergedState } from 'rc-util';
7
7
  import DropArea from './DropArea';
8
8
  import FileList, { type FileListProps } from './FileList';
9
9
  import FileListCard from './FileList/FileListCard';
10
+ import ImageCard from './FileList/ImageCard';
10
11
  import PlaceholderUploader, {
11
12
  type PlaceholderProps,
12
13
  type PlaceholderType,
@@ -92,6 +93,11 @@ export interface AttachmentsProps extends Omit<UploadProps, 'fileList'> {
92
93
  * @descriptionEn Render type, currently only supports default render mode
93
94
  */
94
95
  renderType?: 'default',
96
+ /**
97
+ * @description 图片类型文件是否支持点击刷新按钮直接替换上传
98
+ * @descriptionEn Whether image files support direct replacement upload via the refresh button
99
+ */
100
+ replaceable?: boolean;
95
101
  }
96
102
 
97
103
  export interface AttachmentsRef {
@@ -121,6 +127,7 @@ function Attachments(props: AttachmentsProps, ref: React.Ref<AttachmentsRef>) {
121
127
  onChange,
122
128
  overflow,
123
129
  disabled,
130
+ replaceable,
124
131
  classNames = {},
125
132
  styles = {},
126
133
  ...uploadProps
@@ -170,6 +177,25 @@ function Attachments(props: AttachmentsProps, ref: React.Ref<AttachmentsRef>) {
170
177
  });
171
178
  };
172
179
 
180
+ const onItemReplace = useEvent((oldItem: Attachment, file: File) => {
181
+ const newAttachment: Attachment = {
182
+ uid: oldItem.uid,
183
+ name: file.name,
184
+ size: file.size,
185
+ type: file.type,
186
+ originFileObj: file as any,
187
+ status: 'done',
188
+ percent: 100,
189
+ };
190
+ const newFileList = fileList.map((fileItem) =>
191
+ fileItem.uid === oldItem.uid ? newAttachment : fileItem,
192
+ );
193
+ triggerChange({
194
+ file: newAttachment,
195
+ fileList: newFileList,
196
+ });
197
+ });
198
+
173
199
  let renderChildren: React.ReactElement;
174
200
 
175
201
  const getPlaceholderNode = (
@@ -233,6 +259,7 @@ function Attachments(props: AttachmentsProps, ref: React.Ref<AttachmentsRef>) {
233
259
  prefixCls={prefixCls}
234
260
  items={fileList}
235
261
  onRemove={onItemRemove}
262
+ onReplace={replaceable ? onItemReplace : undefined}
236
263
  overflow={overflow}
237
264
  upload={mergedUploadProps}
238
265
  listClassName={classnames(classNames.list)}
@@ -267,8 +294,10 @@ const ForwardAttachments = React.forwardRef(Attachments) as React.ForwardRefExot
267
294
  AttachmentsProps & React.RefAttributes<AttachmentsRef>
268
295
  > & {
269
296
  FileCard: typeof FileListCard;
297
+ ImageCard: typeof ImageCard;
270
298
  };
271
299
 
272
300
  ForwardAttachments.FileCard = FileListCard;
301
+ ForwardAttachments.ImageCard = ImageCard;
273
302
 
274
303
  export default ForwardAttachments;
@@ -61,7 +61,7 @@ export default createGlobalStyle`
61
61
  }
62
62
 
63
63
  &-type-preview {
64
- width: 56px;
64
+ width: 100px;
65
65
  height: 56px;
66
66
  line-height: 1;
67
67
 
@@ -70,7 +70,7 @@ export default createGlobalStyle`
70
70
  height: 100%;
71
71
  vertical-align: top;
72
72
  object-fit: cover;
73
- border-radius: 5px;
73
+ border-radius: 6px;
74
74
  }
75
75
 
76
76
  .${(p) => p.theme.prefixCls}-attachment-list-card-img-mask {
@@ -83,6 +83,44 @@ export default createGlobalStyle`
83
83
  border-radius: inherit;
84
84
  }
85
85
 
86
+ .${(p) => p.theme.prefixCls}-attachment-list-card-img-hover-mask {
87
+ position: absolute;
88
+ inset: 0;
89
+ display: flex;
90
+ flex-direction: row;
91
+ justify-content: center;
92
+ align-items: center;
93
+ gap: 16px;
94
+ background: rgba(20, 19, 39, 0.45);
95
+ border-radius: 6px;
96
+ opacity: 0;
97
+ transition: opacity 0.2s;
98
+ }
99
+
100
+ &:hover .${(p) => p.theme.prefixCls}-attachment-list-card-img-hover-mask {
101
+ opacity: 1;
102
+ }
103
+
104
+ .${(p) => p.theme.prefixCls}-attachment-list-card-img-action {
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: center;
108
+ width: 20px;
109
+ height: 20px;
110
+ padding: 0;
111
+ border: none;
112
+ background: transparent;
113
+ color: ${(p) => p.theme.colorWhite};
114
+ font-size: 20px;
115
+ cursor: pointer;
116
+ line-height: 1;
117
+ transition: opacity 0.2s;
118
+
119
+ &:hover {
120
+ opacity: 0.8;
121
+ }
122
+ }
123
+
86
124
  &.${(p) => p.theme.prefixCls}-attachment-list-card-status-error {
87
125
 
88
126
  img,
@@ -161,7 +199,9 @@ export default createGlobalStyle`
161
199
 
162
200
  &:hover {
163
201
  border-color: ${(p) => p.theme.colorPrimary};
202
+ }
164
203
 
204
+ &.${(p) => p.theme.prefixCls}-attachment-list-card-type-overview:hover {
165
205
  &::after {
166
206
  content: '';
167
207
  position: absolute;
@@ -173,6 +213,5 @@ export default createGlobalStyle`
173
213
  background-color: rgba(0, 0, 0, 0.45);
174
214
  }
175
215
  }
176
-
177
216
  }
178
217
  `;
@@ -159,6 +159,7 @@ export default forwardRef(function (_, ref) {
159
159
  return <Attachments
160
160
  key={index}
161
161
  items={files}
162
+ replaceable={true}
162
163
  onChange={(info) => handleFileChange(index, info.fileList)}
163
164
  />
164
165
  })
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { Attachment } from '..';
3
- export interface FileListCardProps {
3
+ import type { ImageCardProps } from './ImageCard';
4
+ export interface FileListCardProps extends Pick<ImageCardProps, 'onReplace'> {
4
5
  /**
5
6
  * @description 自定义CSS类名前缀,用于样式隔离和主题定制
6
7
  * @descriptionEn Custom CSS class name prefix for style isolation and theme customization
@@ -12,11 +12,10 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
12
12
  import classnames from 'classnames';
13
13
  import React from 'react';
14
14
  import { AttachmentContext } from "../context";
15
- import { previewImage } from "../util";
16
- import Progress from "./Progress";
17
15
  import Style from "../style/fileCard";
18
16
  import { useProviderContext } from "../..";
19
17
  import { SparkFalseLine } from '@agentscope-ai/icons';
18
+ import ImageCard from "./ImageCard";
20
19
  import { jsx as _jsx } from "react/jsx-runtime";
21
20
  import { jsxs as _jsxs } from "react/jsx-runtime";
22
21
  import { Fragment as _Fragment } from "react/jsx-runtime";
@@ -106,6 +105,7 @@ function FileListCard(props, ref) {
106
105
  getPrefixCls = _useProviderContext.getPrefixCls;
107
106
  var item = props.item,
108
107
  onRemove = props.onRemove,
108
+ onReplace = props.onReplace,
109
109
  className = props.className,
110
110
  style = props.style;
111
111
  var context = React.useContext(AttachmentContext);
@@ -130,7 +130,19 @@ function FileListCard(props, ref) {
130
130
  var isImg = React.useMemo(function () {
131
131
  return matchExt(nameSuffix, IMG_EXTS);
132
132
  }, [nameSuffix]);
133
- var desc = React.useMemo(function () {
133
+ var renderType = props.renderType || 'default';
134
+ var isImgPreview = isImg && (item.originFileObj || item.thumbUrl || item.url) && renderType === 'default';
135
+ if (isImgPreview) {
136
+ return /*#__PURE__*/_jsx(ImageCard, {
137
+ ref: ref,
138
+ item: item,
139
+ onRemove: onRemove,
140
+ onReplace: onReplace,
141
+ className: className,
142
+ style: style
143
+ });
144
+ }
145
+ var desc = function () {
134
146
  if (description) {
135
147
  return description;
136
148
  }
@@ -141,8 +153,8 @@ function FileListCard(props, ref) {
141
153
  return item.response || EMPTY;
142
154
  }
143
155
  return size ? getSize(size) : EMPTY;
144
- }, [status, percent]);
145
- var _React$useMemo3 = React.useMemo(function () {
156
+ }();
157
+ var _ref3 = function () {
146
158
  var _iterator = _createForOfIteratorHelper(PRESET_FILE_ICONS),
147
159
  _step;
148
160
  try {
@@ -163,53 +175,15 @@ function FileListCard(props, ref) {
163
175
  return [/*#__PURE__*/_jsx(IconImage, {
164
176
  url: "https://gw.alicdn.com/imgextra/i1/O1CN01K7jgEj1sywWTkPSGY_!!6000000005836-55-tps-40-40.svg"
165
177
  }, "defaultIcon"), DEFAULT_ICON_COLOR];
166
- }, [nameSuffix]),
167
- _React$useMemo4 = _slicedToArray(_React$useMemo3, 2),
168
- icon = _React$useMemo4[0],
169
- iconColor = _React$useMemo4[1];
170
- var _React$useState = React.useState(),
171
- _React$useState2 = _slicedToArray(_React$useState, 2),
172
- previewImg = _React$useState2[0],
173
- setPreviewImg = _React$useState2[1];
174
- React.useEffect(function () {
175
- if (item.originFileObj) {
176
- var synced = true;
177
- previewImage(item.originFileObj).then(function (url) {
178
- if (synced) {
179
- setPreviewImg(url);
180
- }
181
- });
182
- return function () {
183
- synced = false;
184
- };
185
- }
186
- setPreviewImg(undefined);
187
- }, [item.originFileObj]);
188
- var content = null;
189
- var previewUrl = item.thumbUrl || item.url || previewImg;
190
- var renderType = props.renderType || 'default';
191
- var isImgPreview = isImg && (item.originFileObj || previewUrl) && renderType === 'default';
192
- if (isImgPreview) {
193
- content = /*#__PURE__*/_jsxs(_Fragment, {
194
- children: [previewUrl && /*#__PURE__*/_jsx("img", {
195
- alt: "preview",
196
- src: previewUrl
197
- }), status !== 'done' && /*#__PURE__*/_jsxs("div", {
198
- className: "".concat(cardCls, "-img-mask"),
199
- children: [status === 'uploading' && percent !== undefined && /*#__PURE__*/_jsx(Progress, {
200
- percent: percent,
201
- prefixCls: cardCls
202
- }), status === 'error' && /*#__PURE__*/_jsx("div", {
203
- className: "".concat(cardCls, "-desc"),
204
- children: /*#__PURE__*/_jsx("div", {
205
- className: "".concat(cardCls, "-ellipsis-prefix"),
206
- children: desc
207
- })
208
- })]
209
- })]
210
- });
211
- } else {
212
- content = /*#__PURE__*/_jsxs(_Fragment, {
178
+ }(),
179
+ _ref4 = _slicedToArray(_ref3, 2),
180
+ icon = _ref4[0],
181
+ iconColor = _ref4[1];
182
+ return /*#__PURE__*/_jsxs(_Fragment, {
183
+ children: [/*#__PURE__*/_jsx(Style, {}), /*#__PURE__*/_jsxs("div", {
184
+ className: classnames(cardCls, _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, "".concat(cardCls, "-status-").concat(status), status), "".concat(cardCls, "-type-overview"), true), "".concat(cardCls, "-type-").concat(renderType), true), "".concat(cardCls, "-hoverable"), !disabled && onRemove), className),
185
+ style: style,
186
+ ref: ref,
213
187
  children: [/*#__PURE__*/_jsx("div", {
214
188
  className: "".concat(cardCls, "-icon"),
215
189
  style: {
@@ -228,15 +202,7 @@ function FileListCard(props, ref) {
228
202
  children: desc
229
203
  })
230
204
  })]
231
- })]
232
- });
233
- }
234
- return /*#__PURE__*/_jsxs(_Fragment, {
235
- children: [/*#__PURE__*/_jsx(Style, {}), /*#__PURE__*/_jsxs("div", {
236
- className: classnames(cardCls, _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, "".concat(cardCls, "-status-").concat(status), status), "".concat(cardCls, "-type-preview"), isImgPreview), "".concat(cardCls, "-type-overview"), !isImgPreview), "".concat(cardCls, "-type-").concat(renderType), true), "".concat(cardCls, "-hoverable"), !disabled && onRemove), className),
237
- style: style,
238
- ref: ref,
239
- children: [content, /*#__PURE__*/_jsx("button", {
205
+ }), /*#__PURE__*/_jsx("button", {
240
206
  style: {
241
207
  opacity: !disabled && onRemove ? 1 : 0
242
208
  },
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import type { Attachment } from '..';
3
+ export interface ImageCardProps {
4
+ /**
5
+ * @description 文件附件数据对象,包含文件的基本信息
6
+ * @descriptionEn File attachment data object containing basic file information
7
+ */
8
+ item: Attachment;
9
+ /**
10
+ * @description 文件移除时的回调函数,用于处理文件删除操作
11
+ * @descriptionEn Callback function when file is removed for handling file deletion operations
12
+ */
13
+ onRemove?: (item: Attachment) => void;
14
+ /**
15
+ * @description 替换当前图片的回调,传入原始附件和新选择的文件
16
+ * @descriptionEn Callback to replace current image, receives the original attachment and newly selected file
17
+ */
18
+ onReplace?: (oldItem: Attachment, file: File) => void;
19
+ /**
20
+ * @description 组件的CSS类名
21
+ * @descriptionEn CSS class name for the component
22
+ */
23
+ className?: string;
24
+ /**
25
+ * @description 组件的内联样式对象
26
+ * @descriptionEn Inline style object for the component
27
+ */
28
+ style?: React.CSSProperties;
29
+ }
30
+ declare const _default: React.ForwardRefExoticComponent<ImageCardProps & React.RefAttributes<HTMLDivElement>>;
31
+ export default _default;
@@ -0,0 +1,162 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
3
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
4
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
6
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
7
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
9
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
10
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
11
+ import classnames from 'classnames';
12
+ import React from 'react';
13
+ import { Image } from 'antd';
14
+ import { AttachmentContext } from "../context";
15
+ import { previewImage } from "../util";
16
+ import Progress from "./Progress";
17
+ import Style from "../style/fileCard";
18
+ import { useProviderContext } from "../..";
19
+ import { SparkFalseLine, SparkVisibleLine, SparkReplaceLine } from '@agentscope-ai/icons';
20
+ import { jsx as _jsx } from "react/jsx-runtime";
21
+ import { jsxs as _jsxs } from "react/jsx-runtime";
22
+ import { Fragment as _Fragment } from "react/jsx-runtime";
23
+ var EMPTY = "\xA0";
24
+ var IMG_ACCEPT = 'image/png,image/jpeg,image/jpg,image/gif,image/bmp,image/webp,image/svg+xml';
25
+ function ImageCard(props, ref) {
26
+ var _useProviderContext = useProviderContext(),
27
+ getPrefixCls = _useProviderContext.getPrefixCls;
28
+ var item = props.item,
29
+ onRemove = props.onRemove,
30
+ onReplace = props.onReplace,
31
+ className = props.className,
32
+ style = props.style;
33
+ var context = React.useContext(AttachmentContext);
34
+ var _ref = context || {},
35
+ disabled = _ref.disabled;
36
+ var percent = item.percent,
37
+ _item$status = item.status,
38
+ status = _item$status === void 0 ? 'done' : _item$status,
39
+ description = item.description;
40
+ var prefixCls = getPrefixCls('attachment');
41
+ var cardCls = "".concat(prefixCls, "-list-card");
42
+ var _React$useState = React.useState(false),
43
+ _React$useState2 = _slicedToArray(_React$useState, 2),
44
+ previewVisible = _React$useState2[0],
45
+ setPreviewVisible = _React$useState2[1];
46
+ var fileInputRef = React.useRef(null);
47
+ var previewConfig = React.useMemo(function () {
48
+ return {
49
+ visible: previewVisible,
50
+ onVisibleChange: setPreviewVisible
51
+ };
52
+ }, [previewVisible]);
53
+ var desc = React.useMemo(function () {
54
+ if (description) {
55
+ return description;
56
+ }
57
+ if (status === 'uploading') {
58
+ return "".concat(percent || 0, "%");
59
+ }
60
+ if (status === 'error') {
61
+ return item.response || EMPTY;
62
+ }
63
+ return EMPTY;
64
+ }, [description, status, percent, item.response]);
65
+ var _React$useState3 = React.useState(),
66
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
67
+ previewImg = _React$useState4[0],
68
+ setPreviewImg = _React$useState4[1];
69
+ React.useEffect(function () {
70
+ if (item.originFileObj) {
71
+ var synced = true;
72
+ previewImage(item.originFileObj).then(function (url) {
73
+ if (synced) {
74
+ setPreviewImg(url);
75
+ }
76
+ });
77
+ return function () {
78
+ synced = false;
79
+ };
80
+ }
81
+ setPreviewImg(undefined);
82
+ }, [item.originFileObj]);
83
+ var previewUrl = item.thumbUrl || item.url || previewImg;
84
+ var handleRefreshClick = function handleRefreshClick(e) {
85
+ var _fileInputRef$current;
86
+ e.stopPropagation();
87
+ (_fileInputRef$current = fileInputRef.current) === null || _fileInputRef$current === void 0 || _fileInputRef$current.click();
88
+ };
89
+ var handleFileChange = function handleFileChange(e) {
90
+ var _e$target$files;
91
+ var file = (_e$target$files = e.target.files) === null || _e$target$files === void 0 ? void 0 : _e$target$files[0];
92
+ if (file && onReplace) {
93
+ onReplace(item, file);
94
+ }
95
+ if (fileInputRef.current) {
96
+ fileInputRef.current.value = '';
97
+ }
98
+ };
99
+ return /*#__PURE__*/_jsxs(_Fragment, {
100
+ children: [/*#__PURE__*/_jsx(Style, {}), /*#__PURE__*/_jsxs("div", {
101
+ className: classnames(cardCls, _defineProperty(_defineProperty(_defineProperty({}, "".concat(cardCls, "-status-").concat(status), status), "".concat(cardCls, "-type-preview"), true), "".concat(cardCls, "-hoverable"), !disabled && onRemove), className),
102
+ style: style,
103
+ ref: ref,
104
+ children: [previewUrl && /*#__PURE__*/_jsx("img", {
105
+ alt: "preview",
106
+ src: previewUrl
107
+ }), /*#__PURE__*/_jsx(Image, {
108
+ src: previewUrl,
109
+ style: {
110
+ display: 'none'
111
+ },
112
+ preview: previewConfig
113
+ }), status !== 'done' && /*#__PURE__*/_jsxs("div", {
114
+ className: "".concat(cardCls, "-img-mask"),
115
+ children: [status === 'uploading' && percent !== undefined && /*#__PURE__*/_jsx(Progress, {
116
+ percent: percent,
117
+ prefixCls: cardCls
118
+ }), status === 'error' && /*#__PURE__*/_jsx("div", {
119
+ className: "".concat(cardCls, "-desc"),
120
+ children: /*#__PURE__*/_jsx("div", {
121
+ className: "".concat(cardCls, "-ellipsis-prefix"),
122
+ children: desc
123
+ })
124
+ })]
125
+ }), status === 'done' && /*#__PURE__*/_jsxs("div", {
126
+ className: "".concat(cardCls, "-img-hover-mask"),
127
+ children: [/*#__PURE__*/_jsx("button", {
128
+ className: "".concat(cardCls, "-img-action"),
129
+ onClick: function onClick(e) {
130
+ e.stopPropagation();
131
+ setPreviewVisible(true);
132
+ },
133
+ children: /*#__PURE__*/_jsx(SparkVisibleLine, {})
134
+ }), onReplace && /*#__PURE__*/_jsx("button", {
135
+ className: "".concat(cardCls, "-img-action"),
136
+ onClick: handleRefreshClick,
137
+ children: /*#__PURE__*/_jsx(SparkReplaceLine, {})
138
+ })]
139
+ }), /*#__PURE__*/_jsx("input", {
140
+ ref: fileInputRef,
141
+ type: "file",
142
+ accept: IMG_ACCEPT,
143
+ style: {
144
+ display: 'none'
145
+ },
146
+ onChange: handleFileChange
147
+ }), /*#__PURE__*/_jsx("button", {
148
+ style: {
149
+ opacity: !disabled && onRemove ? 1 : 0
150
+ },
151
+ className: "".concat(cardCls, "-remove"),
152
+ onClick: function onClick() {
153
+ if (!disabled && onRemove) {
154
+ onRemove(item);
155
+ }
156
+ },
157
+ children: /*#__PURE__*/_jsx(SparkFalseLine, {})
158
+ })]
159
+ })]
160
+ });
161
+ }
162
+ export default /*#__PURE__*/React.forwardRef(ImageCard);
@@ -17,6 +17,11 @@ export interface FileListProps {
17
17
  * @descriptionEn Callback function when file is removed for handling file deletion operations
18
18
  */
19
19
  onRemove: (item: Attachment) => void;
20
+ /**
21
+ * @description 替换图片文件的回调,传入原始附件和新选择的文件
22
+ * @descriptionEn Callback to replace an image file, receives the original attachment and newly selected file
23
+ */
24
+ onReplace?: (oldItem: Attachment, file: File) => void;
20
25
  /**
21
26
  * @description 文件列表的溢出处理方式,影响滚动和布局行为
22
27
  * @descriptionEn Overflow handling method for file list, affects scrolling and layout behavior
@@ -24,6 +24,7 @@ export default function FileList(props) {
24
24
  var prefixCls = props.prefixCls,
25
25
  items = props.items,
26
26
  onRemove = props.onRemove,
27
+ onReplace = props.onReplace,
27
28
  overflow = props.overflow,
28
29
  listClassName = props.listClassName,
29
30
  listStyle = props.listStyle,
@@ -108,6 +109,7 @@ export default function FileList(props) {
108
109
  prefixCls: prefixCls,
109
110
  item: item,
110
111
  onRemove: onRemove,
112
+ onReplace: onReplace,
111
113
  className: classnames(motionCls, itemClassName),
112
114
  style: _objectSpread(_objectSpread({}, motionStyle), itemStyle),
113
115
  renderType: props.renderType
@@ -2,6 +2,7 @@ import { type GetProp, type UploadProps } from 'antd';
2
2
  import React from 'react';
3
3
  import { type FileListProps } from './FileList';
4
4
  import FileListCard from './FileList/FileListCard';
5
+ import ImageCard from './FileList/ImageCard';
5
6
  import { type PlaceholderType } from './PlaceholderUploader';
6
7
  export type SemanticType = 'list' | 'item' | 'placeholder';
7
8
  export type Attachment = GetProp<UploadProps, 'fileList'>[number] & {
@@ -78,6 +79,11 @@ export interface AttachmentsProps extends Omit<UploadProps, 'fileList'> {
78
79
  * @descriptionEn Render type, currently only supports default render mode
79
80
  */
80
81
  renderType?: 'default';
82
+ /**
83
+ * @description 图片类型文件是否支持点击刷新按钮直接替换上传
84
+ * @descriptionEn Whether image files support direct replacement upload via the refresh button
85
+ */
86
+ replaceable?: boolean;
81
87
  }
82
88
  export interface AttachmentsRef {
83
89
  /**
@@ -93,5 +99,6 @@ export interface AttachmentsRef {
93
99
  }
94
100
  declare const ForwardAttachments: React.ForwardRefExoticComponent<AttachmentsProps & React.RefAttributes<AttachmentsRef>> & {
95
101
  FileCard: typeof FileListCard;
102
+ ImageCard: typeof ImageCard;
96
103
  };
97
104
  export default ForwardAttachments;
@@ -1,5 +1,5 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- var _excluded = ["prefixCls", "rootClassName", "rootStyle", "className", "style", "items", "children", "getDropContainer", "placeholder", "onChange", "overflow", "disabled", "classNames", "styles"];
2
+ var _excluded = ["prefixCls", "rootClassName", "rootStyle", "className", "style", "items", "children", "getDropContainer", "placeholder", "onChange", "overflow", "disabled", "replaceable", "classNames", "styles"];
3
3
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
4
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
5
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -20,6 +20,7 @@ import { useEvent, useMergedState } from 'rc-util';
20
20
  import DropArea from "./DropArea";
21
21
  import FileList from "./FileList";
22
22
  import FileListCard from "./FileList/FileListCard";
23
+ import ImageCard from "./FileList/ImageCard";
23
24
  import PlaceholderUploader from "./PlaceholderUploader";
24
25
  import SilentUploader from "./SilentUploader";
25
26
  import { AttachmentContext } from "./context";
@@ -40,6 +41,7 @@ function Attachments(props, ref) {
40
41
  onChange = props.onChange,
41
42
  overflow = props.overflow,
42
43
  disabled = props.disabled,
44
+ replaceable = props.replaceable,
43
45
  _props$classNames = props.classNames,
44
46
  classNames = _props$classNames === void 0 ? {} : _props$classNames,
45
47
  _props$styles = props.styles,
@@ -94,6 +96,24 @@ function Attachments(props, ref) {
94
96
  fileList: newFileList
95
97
  });
96
98
  };
99
+ var onItemReplace = useEvent(function (oldItem, file) {
100
+ var newAttachment = {
101
+ uid: oldItem.uid,
102
+ name: file.name,
103
+ size: file.size,
104
+ type: file.type,
105
+ originFileObj: file,
106
+ status: 'done',
107
+ percent: 100
108
+ };
109
+ var newFileList = fileList.map(function (fileItem) {
110
+ return fileItem.uid === oldItem.uid ? newAttachment : fileItem;
111
+ });
112
+ triggerChange({
113
+ file: newAttachment,
114
+ fileList: newFileList
115
+ });
116
+ });
97
117
  var renderChildren;
98
118
  var getPlaceholderNode = function getPlaceholderNode(type, props, ref) {
99
119
  var placeholderContent = typeof placeholder === 'function' ? placeholder(type) : placeholder;
@@ -131,6 +151,7 @@ function Attachments(props, ref) {
131
151
  prefixCls: prefixCls,
132
152
  items: fileList,
133
153
  onRemove: onItemRemove,
154
+ onReplace: replaceable ? onItemReplace : undefined,
134
155
  overflow: overflow,
135
156
  upload: mergedUploadProps,
136
157
  listClassName: classnames(classNames.list),
@@ -158,4 +179,5 @@ function Attachments(props, ref) {
158
179
  }
159
180
  var ForwardAttachments = /*#__PURE__*/React.forwardRef(Attachments);
160
181
  ForwardAttachments.FileCard = FileListCard;
182
+ ForwardAttachments.ImageCard = ImageCard;
161
183
  export default ForwardAttachments;
@@ -1,7 +1,7 @@
1
1
  var _templateObject;
2
2
  function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
3
3
  import { createGlobalStyle } from 'antd-style';
4
- export default createGlobalStyle(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n.", "-attachment-list-card {\n border-radius: ", "px;\n position: relative;\n background: ", ";\n border-width: ", "px;\n border-style: solid;\n border-color: ", ";\n flex: none;\n transition: all 0.3s;\n\n &-name,\n &-desc {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 100%;\n }\n\n &-ellipsis-prefix {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n &-ellipsis-suffix {\n flex: none;\n }\n\n &-type-overview {\n padding: 0 8px;\n display: flex;\n height: 56px;\n gap: ", "px;\n align-items: center;\n width: 140px;\n\n .", "-attachment-list-card-icon {\n display: flex;\n align-items: center;\n }\n\n .", "-attachment-list-card-content {\n flex: auto;\n min-width: 0;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n font-size: ", "px;\n color: ", ";\n }\n\n .", "-attachment-list-card-desc {\n color: ", ";\n font-size: ", "px;\n }\n }\n\n &-type-preview {\n width: 56px;\n height: 56px;\n line-height: 1;\n\n img {\n width: 100%;\n height: 100%;\n vertical-align: top;\n object-fit: cover;\n border-radius: 5px;\n }\n\n .", "-attachment-list-card-img-mask {\n position: absolute;\n inset: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n background: rgba(0, 0, 0, ", ");\n border-radius: inherit;\n }\n\n &.", "-attachment-list-card-status-error {\n\n img,\n .", "-attachment-list-card-img-mask {\n border-radius: calc(", "px - ", "px);\n }\n\n .", "-attachment-list-card-desc {\n padding-inline: ", "px;\n }\n }\n\n .", "-attachment-list-card-progress {\n }\n }\n\n &-remove {\n position: absolute;\n top: -6px;\n right: -6px;\n width: 16px;\n height: 16px;\n line-height: 1;\n font-size: 10px;\n cursor: pointer;\n display: none;\n color: ", ";\n background-color: ", ";\n border-width: ", "px;\n border-style: solid;\n border-color: ", ";\n border-radius: 50%;\n align-items: center;\n justify-content: center;\n transition: all 0.3s;\n z-index: 1;\n\n &:dir(rtl) {\n transform: translate(-50%, -50%);\n }\n }\n\n &:hover &-remove {\n display: flex;\n \n }\n\n &-status-error {\n border-color: ", ";\n\n .", "-attachment-list-card-desc {\n color: ", ";\n }\n }\n\n &-motion {\n\n &-appear-start {\n width: 0;\n transition: none;\n }\n\n &-leave-active {\n opacity: 0;\n width: 0;\n padding-inline: 0;\n border-inline-width: 0;\n margin-inline-end: calc(-1 * ", "px);\n }\n }\n}\n\n.", "-attachment-list-card-hoverable {\n position: relative;\n\n &:hover {\n border-color: ", ";\n\n &::after {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-radius: 5px;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.45);\n }\n }\n\n}\n"])), function (p) {
4
+ export default createGlobalStyle(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n.", "-attachment-list-card {\n border-radius: ", "px;\n position: relative;\n background: ", ";\n border-width: ", "px;\n border-style: solid;\n border-color: ", ";\n flex: none;\n transition: all 0.3s;\n\n &-name,\n &-desc {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 100%;\n }\n\n &-ellipsis-prefix {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n &-ellipsis-suffix {\n flex: none;\n }\n\n &-type-overview {\n padding: 0 8px;\n display: flex;\n height: 56px;\n gap: ", "px;\n align-items: center;\n width: 140px;\n\n .", "-attachment-list-card-icon {\n display: flex;\n align-items: center;\n }\n\n .", "-attachment-list-card-content {\n flex: auto;\n min-width: 0;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n font-size: ", "px;\n color: ", ";\n }\n\n .", "-attachment-list-card-desc {\n color: ", ";\n font-size: ", "px;\n }\n }\n\n &-type-preview {\n width: 100px;\n height: 56px;\n line-height: 1;\n\n img {\n width: 100%;\n height: 100%;\n vertical-align: top;\n object-fit: cover;\n border-radius: 6px;\n }\n\n .", "-attachment-list-card-img-mask {\n position: absolute;\n inset: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n background: rgba(0, 0, 0, ", ");\n border-radius: inherit;\n }\n\n .", "-attachment-list-card-img-hover-mask {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n gap: 16px;\n background: rgba(20, 19, 39, 0.45);\n border-radius: 6px;\n opacity: 0;\n transition: opacity 0.2s;\n }\n\n &:hover .", "-attachment-list-card-img-hover-mask {\n opacity: 1;\n }\n\n .", "-attachment-list-card-img-action {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n padding: 0;\n border: none;\n background: transparent;\n color: ", ";\n font-size: 20px;\n cursor: pointer;\n line-height: 1;\n transition: opacity 0.2s;\n\n &:hover {\n opacity: 0.8;\n }\n }\n\n &.", "-attachment-list-card-status-error {\n\n img,\n .", "-attachment-list-card-img-mask {\n border-radius: calc(", "px - ", "px);\n }\n\n .", "-attachment-list-card-desc {\n padding-inline: ", "px;\n }\n }\n\n .", "-attachment-list-card-progress {\n }\n }\n\n &-remove {\n position: absolute;\n top: -6px;\n right: -6px;\n width: 16px;\n height: 16px;\n line-height: 1;\n font-size: 10px;\n cursor: pointer;\n display: none;\n color: ", ";\n background-color: ", ";\n border-width: ", "px;\n border-style: solid;\n border-color: ", ";\n border-radius: 50%;\n align-items: center;\n justify-content: center;\n transition: all 0.3s;\n z-index: 1;\n\n &:dir(rtl) {\n transform: translate(-50%, -50%);\n }\n }\n\n &:hover &-remove {\n display: flex;\n \n }\n\n &-status-error {\n border-color: ", ";\n\n .", "-attachment-list-card-desc {\n color: ", ";\n }\n }\n\n &-motion {\n\n &-appear-start {\n width: 0;\n transition: none;\n }\n\n &-leave-active {\n opacity: 0;\n width: 0;\n padding-inline: 0;\n border-inline-width: 0;\n margin-inline-end: calc(-1 * ", "px);\n }\n }\n}\n\n.", "-attachment-list-card-hoverable {\n position: relative;\n\n &:hover {\n border-color: ", ";\n }\n\n &.", "-attachment-list-card-type-overview:hover {\n &::after {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n border-radius: 5px;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.45);\n }\n }\n}\n"])), function (p) {
5
5
  return p.theme.prefixCls;
6
6
  }, function (p) {
7
7
  return p.theme.borderRadius;
@@ -35,6 +35,14 @@ export default createGlobalStyle(_templateObject || (_templateObject = _taggedTe
35
35
  return p.theme.prefixCls;
36
36
  }, function (p) {
37
37
  return p.theme.prefixCls;
38
+ }, function (p) {
39
+ return p.theme.prefixCls;
40
+ }, function (p) {
41
+ return p.theme.colorWhite;
42
+ }, function (p) {
43
+ return p.theme.prefixCls;
44
+ }, function (p) {
45
+ return p.theme.prefixCls;
38
46
  }, function (p) {
39
47
  return p.theme.borderRadius;
40
48
  }, function (p) {
@@ -65,4 +73,6 @@ export default createGlobalStyle(_templateObject || (_templateObject = _taggedTe
65
73
  return p.theme.prefixCls;
66
74
  }, function (p) {
67
75
  return p.theme.colorPrimary;
76
+ }, function (p) {
77
+ return p.theme.prefixCls;
68
78
  });
@@ -192,6 +192,7 @@ export default /*#__PURE__*/forwardRef(function (_, ref) {
192
192
  if (!files.length) return null;
193
193
  return /*#__PURE__*/_jsx(Attachments, {
194
194
  items: files,
195
+ replaceable: true,
195
196
  onChange: function onChange(info) {
196
197
  return handleFileChange(index, info.fileList);
197
198
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentscope-ai/chat",
3
- "version": "1.1.53",
3
+ "version": "1.1.54-beta.1773217735669",
4
4
  "description": "a free and open-source chat framework for building excellent LLM-powered chat experiences",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": [