@rainbow-oh/yee-c 0.9.2 → 0.11.0

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.
Files changed (162) hide show
  1. package/dist/cjs/Button/demo/icon.js +1 -1
  2. package/dist/cjs/Input/style/index.less +1 -0
  3. package/dist/cjs/Table/demo/resizable.d.ts +3 -0
  4. package/dist/cjs/Table/demo/resizable.js +143 -0
  5. package/dist/cjs/Table/hooks/useColumnResize.d.ts +30 -0
  6. package/dist/cjs/Table/hooks/useColumnResize.js +217 -0
  7. package/dist/cjs/Table/hooks/useColumns.d.ts +3 -1
  8. package/dist/cjs/Table/hooks/useColumns.js +14 -3
  9. package/dist/cjs/Table/interface.d.ts +49 -0
  10. package/dist/cjs/Table/style/index.less +42 -0
  11. package/dist/cjs/Table/table.js +62 -9
  12. package/dist/cjs/Table/theader/cell.js +46 -4
  13. package/dist/cjs/Table/util/index.d.ts +19 -1
  14. package/dist/cjs/Table/util/index.js +22 -0
  15. package/dist/cjs/Tabs/demo/overflow-center.d.ts +3 -0
  16. package/dist/cjs/Tabs/demo/overflow-center.js +54 -0
  17. package/dist/cjs/Tabs/hooks/useNavListMove.d.ts +2 -1
  18. package/dist/cjs/Tabs/hooks/useNavListMove.js +51 -16
  19. package/dist/cjs/Tabs/hooks/useTabScroll.d.ts +1 -0
  20. package/dist/cjs/Tabs/hooks/useTabScroll.js +5 -1
  21. package/dist/cjs/Tabs/interface.d.ts +10 -1
  22. package/dist/cjs/Tabs/style/index.less +5 -0
  23. package/dist/cjs/Tabs/tab-header/index.d.ts +1 -0
  24. package/dist/cjs/Tabs/tab-header/index.js +11 -3
  25. package/dist/cjs/Tabs/tabs.js +4 -1
  26. package/dist/cjs/Upload/demo/auto-upload.d.ts +3 -0
  27. package/dist/cjs/Upload/demo/auto-upload.js +65 -0
  28. package/dist/cjs/Upload/demo/basic.js +5 -10
  29. package/dist/cjs/Upload/demo/controlled.js +4 -4
  30. package/dist/cjs/Upload/demo/pictureWall.js +14 -13
  31. package/dist/cjs/Upload/dragger.d.ts +2 -1
  32. package/dist/cjs/Upload/dragger.js +32 -21
  33. package/dist/cjs/Upload/index.d.ts +1 -1
  34. package/dist/cjs/Upload/interface.d.ts +67 -120
  35. package/dist/cjs/Upload/style/index.less +40 -13
  36. package/dist/cjs/Upload/upload.d.ts +2 -2
  37. package/dist/cjs/Upload/upload.js +435 -185
  38. package/dist/cjs/Upload/uploaded-list/index.d.ts +2 -1
  39. package/dist/cjs/Upload/uploaded-list/index.js +6 -3
  40. package/dist/cjs/Upload/uploaded-list/uploaded-item.d.ts +6 -3
  41. package/dist/cjs/Upload/uploaded-list/uploaded-item.js +127 -138
  42. package/dist/cjs/locale/interface.d.ts +1 -0
  43. package/dist/cjs/locale/lang/en_US.js +2 -1
  44. package/dist/cjs/locale/lang/ja_JP.js +2 -1
  45. package/dist/cjs/locale/lang/zh_CN.js +2 -1
  46. package/dist/cjs/locale/lang/zh_TW.js +2 -1
  47. package/dist/cjs/style/size.css +2 -1
  48. package/dist/cjs/style/themes.css +1 -1
  49. package/dist/cjs/style/variables.css +3 -2
  50. package/dist/cjs/utils/ax/core.d.ts +3 -1
  51. package/dist/cjs/utils/ax/core.js +24 -37
  52. package/dist/cjs/utils/ax/index.d.ts +3 -1
  53. package/dist/cjs/utils/folder-scanner.d.ts +1 -1
  54. package/dist/cjs/utils/folder-scanner.js +43 -34
  55. package/dist/cjs/version.d.ts +1 -1
  56. package/dist/cjs/version.js +1 -1
  57. package/dist/esm/Button/demo/icon.js +7 -4
  58. package/dist/esm/Input/style/index.less +1 -0
  59. package/dist/esm/Table/demo/resizable.d.ts +3 -0
  60. package/dist/esm/Table/demo/resizable.js +110 -0
  61. package/dist/esm/Table/hooks/useColumnResize.d.ts +30 -0
  62. package/dist/esm/Table/hooks/useColumnResize.js +206 -0
  63. package/dist/esm/Table/hooks/useColumns.d.ts +3 -1
  64. package/dist/esm/Table/hooks/useColumns.js +9 -4
  65. package/dist/esm/Table/interface.d.ts +49 -0
  66. package/dist/esm/Table/style/index.less +42 -0
  67. package/dist/esm/Table/table.js +83 -13
  68. package/dist/esm/Table/theader/cell.js +38 -3
  69. package/dist/esm/Table/util/index.d.ts +19 -1
  70. package/dist/esm/Table/util/index.js +37 -0
  71. package/dist/esm/Tabs/demo/overflow-center.d.ts +3 -0
  72. package/dist/esm/Tabs/demo/overflow-center.js +61 -0
  73. package/dist/esm/Tabs/hooks/useNavListMove.d.ts +2 -1
  74. package/dist/esm/Tabs/hooks/useNavListMove.js +62 -25
  75. package/dist/esm/Tabs/hooks/useTabScroll.d.ts +1 -0
  76. package/dist/esm/Tabs/hooks/useTabScroll.js +9 -0
  77. package/dist/esm/Tabs/interface.d.ts +10 -1
  78. package/dist/esm/Tabs/style/index.less +5 -0
  79. package/dist/esm/Tabs/tab-header/index.d.ts +1 -0
  80. package/dist/esm/Tabs/tab-header/index.js +15 -3
  81. package/dist/esm/Tabs/tabs.js +4 -2
  82. package/dist/esm/Upload/demo/auto-upload.d.ts +3 -0
  83. package/dist/esm/Upload/demo/auto-upload.js +42 -0
  84. package/dist/esm/Upload/demo/basic.js +5 -11
  85. package/dist/esm/Upload/demo/controlled.js +8 -6
  86. package/dist/esm/Upload/demo/pictureWall.js +17 -14
  87. package/dist/esm/Upload/dragger.d.ts +2 -1
  88. package/dist/esm/Upload/dragger.js +10 -5
  89. package/dist/esm/Upload/index.d.ts +1 -1
  90. package/dist/esm/Upload/interface.d.ts +67 -120
  91. package/dist/esm/Upload/style/index.less +40 -13
  92. package/dist/esm/Upload/upload.d.ts +2 -2
  93. package/dist/esm/Upload/upload.js +573 -271
  94. package/dist/esm/Upload/uploaded-list/index.d.ts +2 -1
  95. package/dist/esm/Upload/uploaded-list/index.js +9 -4
  96. package/dist/esm/Upload/uploaded-list/uploaded-item.d.ts +6 -3
  97. package/dist/esm/Upload/uploaded-list/uploaded-item.js +145 -150
  98. package/dist/esm/locale/interface.d.ts +1 -0
  99. package/dist/esm/locale/lang/en_US.js +2 -1
  100. package/dist/esm/locale/lang/ja_JP.js +2 -1
  101. package/dist/esm/locale/lang/zh_CN.js +2 -1
  102. package/dist/esm/locale/lang/zh_TW.js +2 -1
  103. package/dist/esm/style/size.css +2 -1
  104. package/dist/esm/style/themes.css +1 -1
  105. package/dist/esm/style/variables.css +3 -2
  106. package/dist/esm/utils/ax/core.d.ts +3 -1
  107. package/dist/esm/utils/ax/core.js +32 -40
  108. package/dist/esm/utils/ax/index.d.ts +3 -1
  109. package/dist/esm/utils/folder-scanner.d.ts +1 -1
  110. package/dist/esm/utils/folder-scanner.js +76 -75
  111. package/dist/esm/version.d.ts +1 -1
  112. package/dist/esm/version.js +1 -1
  113. package/dist/umd/yee-c.min.css +2 -2
  114. package/dist/umd/yee-c.min.js +1 -1
  115. package/package.json +1 -1
  116. package/src/Button/demo/icon.tsx +5 -3
  117. package/src/Input/style/index.less +1 -0
  118. package/src/Table/demo/resizable.tsx +106 -0
  119. package/src/Table/hooks/useColumnResize.ts +224 -0
  120. package/src/Table/hooks/useColumns.ts +18 -3
  121. package/src/Table/index.en-US.md +7 -0
  122. package/src/Table/index.zh-CN.md +7 -0
  123. package/src/Table/interface.ts +52 -0
  124. package/src/Table/style/index.less +42 -0
  125. package/src/Table/table-resize.test.tsx +234 -0
  126. package/src/Table/table.tsx +90 -13
  127. package/src/Table/theader/cell.tsx +52 -2
  128. package/src/Table/util/index.ts +44 -1
  129. package/src/Tabs/demo/overflow-center.tsx +35 -0
  130. package/src/Tabs/hooks/useNavListMove.ts +60 -18
  131. package/src/Tabs/hooks/useTabScroll.ts +7 -1
  132. package/src/Tabs/index.en-US.md +33 -31
  133. package/src/Tabs/index.zh-CN.md +33 -31
  134. package/src/Tabs/interface.ts +10 -1
  135. package/src/Tabs/style/index.less +5 -0
  136. package/src/Tabs/tab-header/index.tsx +14 -3
  137. package/src/Tabs/tabs.tsx +2 -0
  138. package/src/Upload/demo/auto-upload.tsx +35 -0
  139. package/src/Upload/demo/basic.tsx +7 -11
  140. package/src/Upload/demo/controlled.tsx +12 -8
  141. package/src/Upload/demo/directory.tsx +3 -4
  142. package/src/Upload/demo/drag.tsx +5 -12
  143. package/src/Upload/demo/multiple.tsx +3 -4
  144. package/src/Upload/demo/pictureWall.tsx +22 -21
  145. package/src/Upload/dragger.tsx +47 -34
  146. package/src/Upload/index.en-US.md +63 -43
  147. package/src/Upload/index.ts +8 -1
  148. package/src/Upload/index.zh-CN.md +62 -42
  149. package/src/Upload/interface.ts +68 -120
  150. package/src/Upload/style/index.less +40 -13
  151. package/src/Upload/upload.tsx +546 -215
  152. package/src/Upload/uploaded-list/index.tsx +9 -5
  153. package/src/Upload/uploaded-list/uploaded-item.tsx +199 -228
  154. package/src/locale/interface.ts +1 -0
  155. package/src/locale/lang/en_US.ts +1 -0
  156. package/src/locale/lang/ja_JP.ts +1 -0
  157. package/src/locale/lang/zh_CN.ts +1 -0
  158. package/src/locale/lang/zh_TW.ts +1 -0
  159. package/src/style/size.css +2 -1
  160. package/src/utils/ax/core.ts +28 -41
  161. package/src/utils/folder-scanner.ts +51 -37
  162. package/src/version.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { UploadFile } from '../interface';
2
+ import type { UploadFile } from '../interface';
3
3
  import UploadedItem from './uploaded-item';
4
4
 
5
5
  interface UploadListProps {
@@ -22,25 +22,29 @@ interface UploadListProps {
22
22
  onRemove?: (file: UploadFile) => void;
23
23
  onReUpload?: (file: UploadFile) => void;
24
24
  onPreview?: (file: UploadFile) => void;
25
+ isPreviewable?: (file: UploadFile) => boolean;
25
26
  renderUploadTrigger?: () => React.ReactNode;
26
27
  }
27
28
 
28
29
  const UploadList = (props: UploadListProps) => {
29
- const { prefixCls, fileList, renderUploadTrigger, ...rest } = props;
30
+ const { prefixCls, fileList, isPreviewable, renderUploadTrigger, ...rest } =
31
+ props;
30
32
 
31
33
  if (!Array.isArray(fileList) || fileList.length === 0) {
32
34
  return renderUploadTrigger?.();
33
35
  }
34
36
 
35
37
  return (
36
- <div className={`${prefixCls}-list`}>
37
- {fileList.map((file) => {
38
+ <div className={`${prefixCls}-list`} aria-live="polite">
39
+ {fileList.map((file, index) => {
38
40
  return (
39
41
  <UploadedItem
40
42
  {...rest}
41
43
  prefixCls={prefixCls}
42
44
  file={file}
43
- key={file.uid}
45
+ fileList={fileList}
46
+ previewable={isPreviewable?.(file) ?? false}
47
+ key={file.uid || `${file.name}-${index}`}
44
48
  />
45
49
  );
46
50
  })}
@@ -8,66 +8,65 @@ import {
8
8
  RotateCcw,
9
9
  Trash2,
10
10
  } from 'lucide-react';
11
- import React, { useEffect, useRef, useState } from 'react';
11
+ import React, { useEffect, useState } from 'react';
12
12
 
13
13
  import Button from '../../Button';
14
- import Dialog from '../../Dialog';
15
- import useEvent from '../../hooks/useEvent';
16
14
  import Space from '../../Space';
17
15
  import Spin from '../../Spin';
18
16
  import Tooltip from '../../Tooltip';
19
- import { UploadFile } from '../interface';
17
+ import type { UploadFile } from '../interface';
20
18
  import UploadProgress from '../upload-progress';
21
19
 
22
- type FileStatus = 'uploading' | 'error' | 'success' | 'ready';
20
+ type FileStatus = UploadFile['status'];
23
21
 
24
22
  const fileState: Record<FileStatus, React.ReactElement> = {
25
23
  uploading: <Spin type="spin" size="small" />,
26
- error: <CircleX />,
27
- success: <CircleCheck />,
28
- ready: <Paperclip />,
24
+ error: <CircleX size={14}/>,
25
+ success: <CircleCheck size={14}/>,
26
+ ready: <Paperclip size={14}/>,
29
27
  };
30
28
 
31
- const fileStatusTitle = {
29
+ const fileStatusTitle: Record<FileStatus, string> = {
32
30
  ready: 'Upload Ready',
33
31
  uploading: 'Uploading',
34
32
  error: 'Upload Error',
35
33
  success: 'Upload Success',
36
- } as const;
34
+ };
37
35
 
38
36
  const fileIcon: Record<string, React.ReactNode> = {
39
- image: <Image />,
40
- xlsx: <Paperclip />,
41
- docx: <Paperclip />,
42
- pdf: <Paperclip />,
43
- zip: <Paperclip />,
44
- unknown: <Paperclip />,
37
+ image: <Image size={14} />,
38
+ xlsx: <Paperclip size={14} />,
39
+ docx: <Paperclip size={14} />,
40
+ pdf: <Paperclip size={14} />,
41
+ zip: <Paperclip size={14} />,
42
+ unknown: <Paperclip size={14} />,
45
43
  };
46
44
 
47
45
  const getFileType = (type: string) => {
48
46
  const lower = type?.toLowerCase() || '';
49
- const images = ['jpg', 'jpeg', 'png', 'gif', 'bmp'];
50
- if (images.includes(lower)) {
47
+ const images = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'];
48
+ if (lower.startsWith('image/') || images.includes(lower)) {
51
49
  return 'image';
52
50
  }
53
51
  if (lower === 'xlsx' || lower === 'xls') {
54
52
  return 'xlsx';
55
53
  }
56
- if (lower === 'pdf') {
54
+ if (lower === 'pdf' || lower === 'application/pdf') {
57
55
  return 'pdf';
58
56
  }
59
57
  if (lower === 'docx' || lower === 'doc') {
60
58
  return 'docx';
61
59
  }
62
- if (lower === 'zip') {
60
+ if (lower === 'zip' || lower.includes('zip')) {
63
61
  return 'zip';
64
62
  }
65
63
  return 'unknown';
66
64
  };
67
65
 
68
- function UploadedItem(props: {
66
+ interface UploadedItemProps {
69
67
  prefixCls?: string;
70
68
  file: UploadFile;
69
+ fileList: UploadFile[];
71
70
  listType?: string;
72
71
  progress?: boolean | object;
73
72
  showUploadList?:
@@ -85,10 +84,14 @@ function UploadedItem(props: {
85
84
  onRemove?: (file: UploadFile) => void;
86
85
  onReUpload?: (file: UploadFile) => void;
87
86
  onPreview?: (file: UploadFile) => void;
88
- }) {
87
+ previewable?: boolean;
88
+ }
89
+
90
+ function UploadedItem(props: UploadedItemProps) {
89
91
  const {
90
- prefixCls,
92
+ prefixCls = 'yee-upload',
91
93
  file,
94
+ fileList,
92
95
  listType,
93
96
  progress,
94
97
  showUploadList,
@@ -96,60 +99,50 @@ function UploadedItem(props: {
96
99
  onRemove,
97
100
  onReUpload,
98
101
  onPreview,
102
+ previewable = false,
99
103
  } = props;
100
104
 
101
- const {
102
- showTooltip = true,
103
- showReload = true,
104
- showRemoveIcon = true,
105
- showPreviewIcon = true,
106
- reloadIcon,
107
- removeIcon,
108
- previewIcon,
109
- } = typeof showUploadList === 'object' ? showUploadList : ({} as any);
105
+ const uploadListConfig =
106
+ typeof showUploadList === 'object' ? showUploadList : undefined;
107
+ const showTooltip = uploadListConfig?.showTooltip ?? true;
108
+ const showReload = uploadListConfig?.showReload ?? true;
109
+ const showRemoveIcon = uploadListConfig?.showRemoveIcon ?? true;
110
+ const showPreviewIcon = uploadListConfig?.showPreviewIcon ?? true;
111
+ const reloadIcon = uploadListConfig?.reloadIcon;
112
+ const removeIcon = uploadListConfig?.removeIcon;
113
+ const previewIcon = uploadListConfig?.previewIcon;
110
114
 
111
- const [objectUrl, setObjectUrl] = useState<string>('');
112
- const [imagePreviewOpen, setImagePreviewOpen] = useState(false);
113
- const previewImageSrc = useRef<string>('');
115
+ const [objectUrl, setObjectUrl] = useState('');
114
116
 
115
- // Create and clean up object URL to prevent memory leaks
116
117
  useEffect(() => {
117
- if (file.raw && file.raw instanceof File) {
118
+ if (file.raw instanceof File) {
118
119
  const url = URL.createObjectURL(file.raw);
119
120
  setObjectUrl(url);
120
-
121
- return () => {
122
- URL.revokeObjectURL(url);
123
- };
121
+ return () => URL.revokeObjectURL(url);
124
122
  }
123
+ setObjectUrl('');
124
+ return undefined;
125
125
  }, [file.raw]);
126
126
 
127
- const closeDialog = useEvent(() => {
128
- setImagePreviewOpen(false);
129
- });
130
-
131
- const showImage = () => {
132
- if (onPreview) {
133
- onPreview(file);
134
- } else if (objectUrl) {
135
- previewImageSrc.current = objectUrl;
136
- setImagePreviewOpen(true);
137
- }
138
- };
127
+ const previewSrc = file.url || objectUrl;
128
+ const inferredType = file.type || file.name.split('.').pop() || '';
129
+ const fileType = getFileType(inferredType);
130
+ const isImage = fileType === 'image';
139
131
 
140
132
  const renderReload = () => {
141
133
  if (!showReload) {
142
134
  return null;
143
135
  }
144
- const icon = reloadIcon || <RotateCcw size={18} />;
145
136
  return (
146
137
  <Button
147
138
  size="small"
148
- icon={icon}
139
+ icon={reloadIcon || <RotateCcw size={18} />}
149
140
  variant="text"
150
141
  color="danger"
151
- onClick={(e) => {
152
- e.stopPropagation();
142
+ aria-label={`Retry ${file.name}`}
143
+ title={`Retry ${file.name}`}
144
+ onClick={(event) => {
145
+ event.stopPropagation();
153
146
  onReUpload?.(file);
154
147
  }}
155
148
  />
@@ -160,15 +153,16 @@ function UploadedItem(props: {
160
153
  if (!showRemoveIcon) {
161
154
  return null;
162
155
  }
163
- const icon = removeIcon || <Trash2 size={18} />;
164
156
  return (
165
157
  <Button
166
158
  size="small"
167
- icon={icon}
159
+ icon={removeIcon || <Trash2 size={16} />}
168
160
  variant="text"
169
161
  color="danger"
170
- onClick={(e) => {
171
- e.stopPropagation();
162
+ aria-label={`Remove ${file.name}`}
163
+ title={`Remove ${file.name}`}
164
+ onClick={(event) => {
165
+ event.stopPropagation();
172
166
  onRemove?.(file);
173
167
  }}
174
168
  />
@@ -176,205 +170,182 @@ function UploadedItem(props: {
176
170
  };
177
171
 
178
172
  const renderPreview = () => {
179
- if (!showPreviewIcon) {
173
+ if (!showPreviewIcon || !isImage || !previewable) {
180
174
  return null;
181
175
  }
182
- const icon = previewIcon || <Eye size={18} />;
183
- const fileType = getFileType(file.type || '');
176
+ return (
177
+ <Button
178
+ size="small"
179
+ icon={previewIcon || <Eye size={16} />}
180
+ variant="text"
181
+ aria-label={`Preview ${file.name}`}
182
+ title={`Preview ${file.name}`}
183
+ onClick={(event) => {
184
+ event.stopPropagation();
185
+ onPreview?.(file);
186
+ }}
187
+ />
188
+ );
189
+ };
184
190
 
185
- if (fileType === 'image' || file.type?.startsWith('image/')) {
186
- return (
187
- <Button
188
- size="small"
189
- icon={icon}
190
- variant="text"
191
- onClick={(e) => {
192
- e.stopPropagation();
193
- showImage();
194
- }}
195
- />
196
- );
191
+ const getShowCase = () => {
192
+ if (file.status === 'error' || !isImage) {
193
+ return fileIcon[fileType] || <Paperclip size={14} />;
197
194
  }
198
-
199
- return null;
195
+ if (previewSrc) {
196
+ return <img src={previewSrc} alt={file.name} />;
197
+ }
198
+ return fileIcon[fileType] || <Paperclip size={14} />;
200
199
  };
201
200
 
202
201
  if (listType === 'picture-wall') {
203
- const fileType = getFileType(file.type || '');
204
-
205
- const getShowCase = () => {
206
- if (file.status === 'error' || fileType !== 'image') {
207
- return fileIcon[fileType] || <Paperclip size={18} />;
208
- }
209
-
210
- if (fileType === 'image' && objectUrl) {
211
- return <img src={objectUrl} alt={file.name} />;
212
- }
213
-
214
- return fileIcon[fileType] || <Paperclip size={18} />;
215
- };
216
-
217
202
  return (
218
- <>
219
- <div
220
- className={clsx(`${prefixCls}-picture-wall-item`, {
221
- [`${prefixCls}-state-` + file.status]: file.status,
222
- })}
223
- key={file.uid}
224
- >
225
- {file.status === 'uploading' ? (
226
- <UploadProgress file={file} progress={progress} />
227
- ) : (
228
- <>
229
- {file.status === 'error' ? (
230
- <div className={`${prefixCls}-picture-wall-item-error`}>
231
- {getShowCase()}
203
+ <div
204
+ className={clsx(`${prefixCls}-picture-wall-item`, {
205
+ [`${prefixCls}-state-${file.status}`]: file.status,
206
+ })}
207
+ aria-label={`${file.name}: ${fileStatusTitle[file.status]}`}
208
+ >
209
+ {file.status === 'uploading' ? (
210
+ <UploadProgress
211
+ prefixCls={prefixCls}
212
+ file={file}
213
+ progress={progress}
214
+ />
215
+ ) : (
216
+ <>
217
+ {file.status === 'error' ? (
218
+ <div className={`${prefixCls}-picture-wall-item-error`}>
219
+ {getShowCase()}
220
+ <span className={`${prefixCls}-picture-wall-name`}>
221
+ {file.name}
222
+ </span>
223
+ </div>
224
+ ) : (
225
+ <div className={`${prefixCls}-picture-wall-item-content`}>
226
+ {getShowCase()}
227
+ {!isImage && (
232
228
  <span className={`${prefixCls}-picture-wall-name`}>
233
229
  {file.name}
234
230
  </span>
235
- </div>
236
- ) : (
237
- <div className={`${prefixCls}-picture-wall-item-content`}>
238
- {getShowCase()}
239
- {fileType !== 'image' && (
240
- <span className={`${prefixCls}-picture-wall-name`}>
241
- {file.name}
242
- </span>
243
- )}
244
- </div>
245
- )}
246
- <div className={`${prefixCls}-picture-wall-item-operate`}>
247
- {file.status === 'error' ? (
248
- renderReload()
249
- ) : (
250
- <>
251
- {renderPreview()}
252
- {renderTrash()}
253
- </>
254
231
  )}
255
232
  </div>
256
- </>
257
- )}
258
- </div>
259
- <Dialog
260
- className={`${prefixCls}-picture-dialog`}
261
- open={imagePreviewOpen}
262
- onCancel={closeDialog}
263
- footer={false}
264
- >
265
- <img
266
- src={previewImageSrc.current}
267
- alt="preview"
268
- style={{ maxWidth: '100%' }}
269
- />
270
- </Dialog>
271
- </>
233
+ )}
234
+ <div className={`${prefixCls}-picture-wall-item-operate`}>
235
+ {file.status === 'error' ? (
236
+ renderReload()
237
+ ) : (
238
+ <>
239
+ {renderPreview()}
240
+ {renderTrash()}
241
+ </>
242
+ )}
243
+ </div>
244
+ </>
245
+ )}
246
+ </div>
272
247
  );
273
248
  }
274
249
 
275
250
  if (listType === 'picture-list') {
276
- const fileType = getFileType(file.type || '');
277
-
278
251
  return (
279
- <>
280
- <div
281
- className={clsx(`${prefixCls}-picture-list-item`, {
282
- [`${prefixCls}-state-` + file.status]: file.status,
283
- })}
284
- key={file.uid}
285
- >
286
- {file.status === 'uploading' ? (
287
- <div className={`${prefixCls}-uploading`}>
288
- <Spin className={`${prefixCls}-uploading-spin`} type="spin" />
289
- <div className={`${prefixCls}-uploading-content`}>
290
- <div>{file.name ? file.name : 'Uploading...'}</div>
291
- <UploadProgress file={file} progress={progress} />
292
- </div>
293
- </div>
294
- ) : (
295
- <>
296
- <div className={`${prefixCls}-picture-list-item-content`}>
297
- {file.status === 'error' ? (
298
- <Image />
299
- ) : (
300
- <>
301
- {fileType === 'image' && objectUrl ? (
302
- <img
303
- className={`${prefixCls}-picture-list-header-img`}
304
- src={objectUrl}
305
- alt={file.name}
306
- />
307
- ) : (
308
- fileIcon[fileType] || <Image />
309
- )}
310
- </>
311
- )}
312
- <span>{file.name}</span>
313
- </div>
314
-
315
- <div className={`${prefixCls}-picture-list-item-operate`}>
316
- {file.status === 'error' && renderReload()}
317
- {renderPreview()}
318
- {renderTrash()}
319
- </div>
320
- </>
321
- )}
322
- </div>
323
- </>
324
- );
325
- }
326
-
327
- const renderItem = () => {
328
- const node = (
329
252
  <div
330
- className={clsx(`${prefixCls}-list-item`, {
331
- [`${prefixCls}-state-` + file.status]: file.status,
332
- [`${prefixCls}-list-item-clickable`]: !!onPreview,
253
+ className={clsx(`${prefixCls}-picture-list-item`, {
254
+ [`${prefixCls}-state-${file.status}`]: file.status,
333
255
  })}
334
- onClick={() => onPreview?.(file)}
335
- key={file.uid}
256
+ aria-label={`${file.name}: ${fileStatusTitle[file.status]}`}
336
257
  >
337
- <div style={{ display: 'flex', alignItems: 'center' }}>
338
- <div className={`${prefixCls}-item-icon`}>
339
- {fileState[file.status as FileStatus] || <Paperclip size={18} />}
258
+ {file.status === 'uploading' ? (
259
+ <div className={`${prefixCls}-uploading`}>
260
+ <Spin className={`${prefixCls}-uploading-spin`} type="spin" />
261
+ <div className={`${prefixCls}-uploading-content`}>
262
+ <div>{file.name || 'Uploading...'}</div>
263
+ <UploadProgress
264
+ prefixCls={prefixCls}
265
+ file={file}
266
+ progress={progress}
267
+ />
268
+ </div>
340
269
  </div>
341
- <span className={`${prefixCls}-item-name-content`}>{file.name}</span>
342
- </div>
343
- {file.status !== 'uploading' && (
344
- <Space
345
- className={`${prefixCls}-item-operate`}
346
- gap={8}
347
- onClick={(event) => event.stopPropagation()}
348
- >
349
- {itemRender?.(file, [])}
350
- {file.status === 'error' ? renderReload() : renderPreview()}
351
- {renderTrash()}
352
- </Space>
270
+ ) : (
271
+ <>
272
+ <div className={`${prefixCls}-picture-list-item-content`}>
273
+ {file.status === 'error' ? (
274
+ <Image />
275
+ ) : isImage && previewSrc ? (
276
+ <img
277
+ className={`${prefixCls}-picture-list-header-img`}
278
+ src={previewSrc}
279
+ alt={file.name}
280
+ />
281
+ ) : (
282
+ fileIcon[fileType] || <Image size={14} />
283
+ )}
284
+ <span>{file.name}</span>
285
+ </div>
286
+ <div className={`${prefixCls}-picture-list-item-operate`}>
287
+ {file.status === 'error' && renderReload()}
288
+ {renderPreview()}
289
+ {renderTrash()}
290
+ </div>
291
+ </>
353
292
  )}
354
293
  </div>
355
294
  );
295
+ }
356
296
 
357
- if (showTooltip) {
358
- return (
359
- <Tooltip
360
- title={
361
- fileStatusTitle[file.status as FileStatus] || fileStatusTitle.ready
362
- }
297
+ const itemNode = (
298
+ <div
299
+ className={clsx(`${prefixCls}-list-item`, {
300
+ [`${prefixCls}-state-${file.status}`]: file.status,
301
+ [`${prefixCls}-list-item-clickable`]: previewable,
302
+ })}
303
+ role={previewable ? 'button' : undefined}
304
+ tabIndex={previewable ? 0 : undefined}
305
+ aria-label={`${file.name}: ${fileStatusTitle[file.status]}`}
306
+ onClick={() => previewable && onPreview?.(file)}
307
+ onKeyDown={(event) => {
308
+ if (previewable && (event.key === 'Enter' || event.key === ' ')) {
309
+ event.preventDefault();
310
+ onPreview?.(file);
311
+ }
312
+ }}
313
+ >
314
+ <div className={`${prefixCls}-item-label`}>
315
+ <div className={`${prefixCls}-item-icon`} aria-hidden="true">
316
+ {fileState[file.status] || <Paperclip size={14} />}
317
+ </div>
318
+ <span className={`${prefixCls}-item-name-content`}>{file.name}</span>
319
+ </div>
320
+ {file.status !== 'uploading' && (
321
+ <Space
322
+ className={`${prefixCls}-item-operate`}
323
+ gap={8}
324
+ onClick={(event) => event.stopPropagation()}
363
325
  >
364
- {node}
365
- </Tooltip>
366
- );
367
- }
368
-
369
- return node;
370
- };
326
+ {itemRender?.(file, fileList)}
327
+ {file.status === 'error' ? renderReload() : renderPreview()}
328
+ {renderTrash()}
329
+ </Space>
330
+ )}
331
+ </div>
332
+ );
371
333
 
372
334
  return (
373
335
  <>
374
- {renderItem()}
336
+ {showTooltip ? (
337
+ <Tooltip title={fileStatusTitle[file.status]}>{itemNode}</Tooltip>
338
+ ) : (
339
+ itemNode
340
+ )}
375
341
  {file.status === 'uploading' && (
376
342
  <div className={`${prefixCls}-item-progress`} title={file.name}>
377
- <UploadProgress file={file} progress={progress} showInfo />
343
+ <UploadProgress
344
+ prefixCls={prefixCls}
345
+ file={file}
346
+ progress={progress}
347
+ showInfo
348
+ />
378
349
  </div>
379
350
  )}
380
351
  </>
@@ -79,6 +79,7 @@ export interface LocaleTable {
79
79
  sortAscending?: string; // "Click to sort ascending"
80
80
  sortDescending?: string; // "Click to sort descending"
81
81
  sortCancel?: string; // "Click to cancel sorting"
82
+ resizeColumn?: string; // "Drag to resize column"
82
83
  }
83
84
 
84
85
  // Pagination component
@@ -105,6 +105,7 @@ const locale: Locale = {
105
105
  sortAscending: 'Click to sort ascending',
106
106
  sortDescending: 'Click to sort descending',
107
107
  sortCancel: 'Click to cancel sorting',
108
+ resizeColumn: 'Drag to resize column',
108
109
  },
109
110
 
110
111
  pagination: {
@@ -105,6 +105,7 @@ const locale: Locale = {
105
105
  sortAscending: 'クリックで昇順に並べ替え',
106
106
  sortDescending: 'クリックで降順に並べ替え',
107
107
  sortCancel: 'クリックで並べ替えを解除',
108
+ resizeColumn: 'ドラッグで列幅を変更',
108
109
  },
109
110
 
110
111
  pagination: {
@@ -96,6 +96,7 @@ const locale: Locale = {
96
96
  sortAscending: '点击升序排列',
97
97
  sortDescending: '点击降序排列',
98
98
  sortCancel: '点击取消排序',
99
+ resizeColumn: '拖动调整列宽',
99
100
  },
100
101
 
101
102
  pagination: {
@@ -96,6 +96,7 @@ const locale: Locale = {
96
96
  sortAscending: '點擊升序排列',
97
97
  sortDescending: '點擊降序排列',
98
98
  sortCancel: '點擊取消排序',
99
+ resizeColumn: '拖動調整欄寬',
99
100
  },
100
101
 
101
102
  pagination: {
@@ -674,6 +674,7 @@
674
674
  --yee-table-bordered-cell-border-width: 1px;
675
675
  --yee-table-bordered-thead-border-width: 1px;
676
676
  --yee-table-thead-action-gap: 8px;
677
+ --yee-table-resize-handle-width: 8px;
677
678
  --yee-table-filter-popup-padding: 8px;
678
679
  --yee-table-content-border-radius: 6px 6px 0 0;
679
680
  --yee-table-cell-padding: 13px 16px;
@@ -743,7 +744,7 @@
743
744
  --yee-tabs-operation-container-margin-top: -8px;
744
745
  --yee-tabs-operation-container-padding: 4px 0;
745
746
  --yee-tabs-operation-tab-height: 32px;
746
- --yee-tabs-operation-tab-padding: 5px 12px;
747
+ --yee-tabs-operation-tab-padding: 0 12px;
747
748
  --yee-tabs-tab-group-margin-left: 4px;
748
749
  --yee-tabs-tab-group-container-padding: 8px;
749
750
  --yee-tabs-tab-group-container-line-height: 32px;