@zjlab-fe/data-hub-ui 0.32.6 → 0.33.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.
- package/dist/types/components/FileUploader/UploadStoreProvider/UploadStoreProvider.d.ts +4 -1
- package/dist/types/components/SDK-modal/document-link.d.ts +1 -3
- package/dist/types/components/SDK-modal/index.d.ts +4 -0
- package/dist/types/components/SDK-modal/inner-modal.d.ts +9 -0
- package/dist/types/components/SDK-modal/types.d.ts +4 -3
- package/dist/types/components/apply-perm-modal/index.d.ts +14 -5
- package/dist/types/components/confirm-again/index.d.ts +8 -1
- package/dist/types/components/copy/index.d.ts +9 -4
- package/dist/types/components/limit-credit-modal/index.d.ts +9 -3
- package/dist/types/components/tag-group-filter/dataSizeFilter.d.ts +0 -1
- package/dist/types/components/tag-group-filter/index.d.ts +4 -1
- package/dist/types/index.d.ts +7 -5
- package/dist/types/locale/index.d.ts +18 -0
- package/dist/types/locale/modalHolder.d.ts +11 -0
- package/dist/types/locale/resolveLocale.d.ts +9 -0
- package/dist/types/locale/translations.d.ts +808 -0
- package/dist/types/locale/types.d.ts +32 -0
- package/es/components/FileUploader/Locale/useTranslate.js +34 -11
- package/es/components/FileUploader/UploadStoreProvider/UploadStoreProvider.js +5 -3
- package/es/components/FileUploader/hooks/useOnMountedResumeUnfinished.js +6 -3
- package/es/components/SDK-modal/document-link.js +5 -2
- package/es/components/SDK-modal/index.js +29 -2
- package/es/components/SDK-modal/inner-modal.js +23 -12
- package/es/components/apply-perm-modal/index.js +20 -8
- package/es/components/confirm-again/index.js +12 -2
- package/es/components/copy/index.js +21 -7
- package/es/components/data-table/index.js +15 -4
- package/es/components/dataset-batch-action/index.js +48 -25
- package/es/components/file-preview/data-table/index.js +4 -3
- package/es/components/file-preview/index.js +5 -4
- package/es/components/file-uploader/components/uploader-drop-zone.js +4 -2
- package/es/components/file-uploader/components/uploader-file-item.js +12 -9
- package/es/components/file-uploader/components/uploader-file-list.js +6 -3
- package/es/components/file-uploader/components/uploader.js +4 -2
- package/es/components/file-uploader/components/uploading-status.js +18 -12
- package/es/components/header/index.js +3 -1
- package/es/components/input-tag/index.js +5 -2
- package/es/components/limit-credit-modal/index.js +38 -19
- package/es/components/menu/index.js +5 -2
- package/es/components/notion-editor/code-block/languages.js +1 -1
- package/es/components/notion-editor/index.js +23 -13
- package/es/components/operator-chain/components/AddButton.js +3 -1
- package/es/components/operator-chain/components/IOCard.js +4 -1
- package/es/components/operator-chain/components/VirtualDropdown.js +6 -3
- package/es/components/permission-editor/index.js +1 -0
- package/es/components/permission-editor/permissionEditModal/index.js +7 -4
- package/es/components/permission-editor/permissionEditor/index.js +40 -75
- package/es/components/permission-editor/permissionViewPopover/index.js +5 -2
- package/es/components/tag-group-filter/dataSizeFilter.js +6 -3
- package/es/components/tag-group-filter/index.js +2 -2
- package/es/components/tip-tap/bubble-menu.js +8 -3
- package/es/components/tip-tap/editor.js +5 -2
- package/es/components/tip-tap/extensions/index.js +1 -1
- package/es/components/tip-tap/toolbar/components/color-picker.js +3 -1
- package/es/components/tip-tap/toolbar/components/heading-dropdown.js +8 -5
- package/es/components/tip-tap/toolbar/components/link-button.js +4 -1
- package/es/components/tip-tap/toolbar/components/table-button.js +5 -2
- package/es/components/tip-tap/toolbar/index.js +4 -1
- package/es/components/uploadDrawer/fileUploadDrawer.js +6 -2
- package/es/components/uploadDrawer/fileUploadDrawerList.js +4 -1
- package/es/components/uploadDrawer/fileUploadDrawerListProgressButton.js +4 -2
- package/es/components/uploadDrawer/hooks/useCancelUpload.js +3 -1
- package/es/components/uploadDrawer/hooks/useFilterFiles.js +7 -4
- package/es/components/uploadDrawer/hooks/useFormatFiles.js +3 -1
- package/es/components/uploadDrawer/hooks/useResumeUnfinishedUploads.js +7 -6
- package/es/components/uploadDrawer/index.js +4 -2
- package/es/index.js +6 -5
- package/es/locale/index.js +64 -0
- package/es/locale/modalHolder.js +21 -0
- package/es/locale/resolveLocale.js +73 -0
- package/es/locale/translations.js +273 -0
- package/lib/index.js +1 -1
- package/package.json +7 -3
|
@@ -3,8 +3,11 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
3
3
|
import { useState, useEffect } from 'react';
|
|
4
4
|
import { Modal, Button, message } from 'antd';
|
|
5
5
|
import PermissionEditor from '../permissionEditor/index.js';
|
|
6
|
+
import { useLocale } from '../../../locale/index.js';
|
|
6
7
|
|
|
7
8
|
const PermissionEditModal = ({ open, onCancel, onSave, initialPermissions = [], }) => {
|
|
9
|
+
const { locale } = useLocale();
|
|
10
|
+
const texts = locale.PermissionEditor;
|
|
8
11
|
const [selectedPermissions, setSelectedPermissions] = useState(initialPermissions);
|
|
9
12
|
const [loading, setLoading] = useState(false);
|
|
10
13
|
// 当 modal 打开时重置权限状态
|
|
@@ -19,7 +22,7 @@ const PermissionEditModal = ({ open, onCancel, onSave, initialPermissions = [],
|
|
|
19
22
|
onCancel();
|
|
20
23
|
}
|
|
21
24
|
catch (error) {
|
|
22
|
-
message.error(
|
|
25
|
+
message.error(texts.updateFailed);
|
|
23
26
|
console.error('保存权限失败:', error);
|
|
24
27
|
}
|
|
25
28
|
});
|
|
@@ -28,9 +31,9 @@ const PermissionEditModal = ({ open, onCancel, onSave, initialPermissions = [],
|
|
|
28
31
|
setSelectedPermissions(initialPermissions);
|
|
29
32
|
onCancel();
|
|
30
33
|
};
|
|
31
|
-
return (jsx(Modal, { title:
|
|
32
|
-
jsx(Button, { onClick: handleCancel, children:
|
|
33
|
-
jsx(Button, { type: "primary", loading: loading, onClick: handleSave, children:
|
|
34
|
+
return (jsx(Modal, { title: texts.title, open: open, onCancel: handleCancel, width: 600, destroyOnClose: true, footer: [
|
|
35
|
+
jsx(Button, { onClick: handleCancel, children: texts.cancel }, "cancel"),
|
|
36
|
+
jsx(Button, { type: "primary", loading: loading, onClick: handleSave, children: texts.save }, "save"),
|
|
34
37
|
], children: jsx("div", { style: { padding: '16px 0' }, children: jsx(PermissionEditor, { initialPermissions: selectedPermissions, onChange: setSelectedPermissions, editable: true }) }) }));
|
|
35
38
|
};
|
|
36
39
|
|
|
@@ -3,103 +3,67 @@ import React from 'react';
|
|
|
3
3
|
import { Tag, Flex } from 'antd';
|
|
4
4
|
import { unEditable, tagReadonly } from './index.module.scss.js';
|
|
5
5
|
import { CheckCircleOutlined } from '@ant-design/icons';
|
|
6
|
+
import { useLocale } from '../../../locale/index.js';
|
|
6
7
|
|
|
7
8
|
const permissionTags = [
|
|
8
9
|
{
|
|
9
|
-
label: '数据权限',
|
|
10
10
|
value: 'agentic',
|
|
11
11
|
readOnly: false,
|
|
12
|
-
children: [
|
|
13
|
-
{
|
|
14
|
-
label: '检索智能体',
|
|
15
|
-
value: '13',
|
|
16
|
-
readOnly: false,
|
|
17
|
-
},
|
|
18
|
-
],
|
|
12
|
+
children: [{ value: '13', readOnly: false }],
|
|
19
13
|
},
|
|
20
14
|
{
|
|
21
|
-
label: '工作台权限',
|
|
22
15
|
value: 'workbench',
|
|
23
16
|
readOnly: false,
|
|
24
17
|
children: [
|
|
25
|
-
{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
readOnly: false,
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
label: '可视化工作流',
|
|
37
|
-
value: '1',
|
|
38
|
-
readOnly: false,
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
label: '文档标注',
|
|
42
|
-
value: '8',
|
|
43
|
-
readOnly: false,
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
label: '模型训练',
|
|
47
|
-
value: '19',
|
|
48
|
-
readOnly: false,
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
label: '计量中心',
|
|
52
|
-
value: '23',
|
|
53
|
-
readOnly: false,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
label: '模型部署',
|
|
57
|
-
value: '21',
|
|
58
|
-
readOnly: true,
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
label: '模型管理',
|
|
62
|
-
value: '22',
|
|
63
|
-
readOnly: true,
|
|
64
|
-
},
|
|
18
|
+
{ value: '20', readOnly: false },
|
|
19
|
+
{ value: '18', readOnly: false },
|
|
20
|
+
{ value: '1', readOnly: false },
|
|
21
|
+
{ value: '8', readOnly: false },
|
|
22
|
+
{ value: '19', readOnly: false },
|
|
23
|
+
{ value: '23', readOnly: false },
|
|
24
|
+
{ value: '21', readOnly: true },
|
|
25
|
+
{ value: '22', readOnly: true },
|
|
65
26
|
],
|
|
66
27
|
},
|
|
67
28
|
{
|
|
68
|
-
label: '语料检索权限',
|
|
69
29
|
value: 'corpus_index',
|
|
70
30
|
readOnly: false,
|
|
71
31
|
children: [
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
value: '14',
|
|
75
|
-
readOnly: false,
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
label: '网页语料筛选',
|
|
79
|
-
value: '15',
|
|
80
|
-
readOnly: false,
|
|
81
|
-
},
|
|
32
|
+
{ value: '14', readOnly: false },
|
|
33
|
+
{ value: '15', readOnly: false },
|
|
82
34
|
],
|
|
83
35
|
},
|
|
84
36
|
{
|
|
85
|
-
label: '语料生产权限',
|
|
86
37
|
value: 'corpus_product',
|
|
87
38
|
readOnly: false,
|
|
88
39
|
children: [
|
|
89
|
-
{
|
|
90
|
-
|
|
91
|
-
value: '16',
|
|
92
|
-
readOnly: false,
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
label: '网页语料生产',
|
|
96
|
-
value: '17',
|
|
97
|
-
readOnly: false,
|
|
98
|
-
},
|
|
40
|
+
{ value: '16', readOnly: false },
|
|
41
|
+
{ value: '17', readOnly: false },
|
|
99
42
|
],
|
|
100
43
|
},
|
|
101
44
|
];
|
|
45
|
+
const PERMISSION_LABEL_KEY = {
|
|
46
|
+
agentic: 'agentic',
|
|
47
|
+
'13': 'agenticSearch',
|
|
48
|
+
workbench: 'workbench',
|
|
49
|
+
'20': 'corpusProductionService',
|
|
50
|
+
'18': 'corpusQuality',
|
|
51
|
+
'1': 'visualWorkflow',
|
|
52
|
+
'8': 'documentAnnotation',
|
|
53
|
+
'19': 'modelTraining',
|
|
54
|
+
'23': 'meteringCenter',
|
|
55
|
+
'21': 'modelDeploy',
|
|
56
|
+
'22': 'modelManage',
|
|
57
|
+
corpus_index: 'corpusIndex',
|
|
58
|
+
'14': 'literatureSearch',
|
|
59
|
+
'15': 'webFilter',
|
|
60
|
+
corpus_product: 'corpusProduct',
|
|
61
|
+
'16': 'documentProduction',
|
|
62
|
+
'17': 'webProduction',
|
|
63
|
+
};
|
|
102
64
|
const PermissionEditor = ({ initialPermissions = [], onChange, editable = true, }) => {
|
|
65
|
+
const { locale } = useLocale();
|
|
66
|
+
const texts = locale.PermissionEditor;
|
|
103
67
|
// 将新格式转换为内部使用的扁平化格式
|
|
104
68
|
const convertToFlatFormat = (permissions) => {
|
|
105
69
|
const flatTags = [];
|
|
@@ -225,9 +189,9 @@ const PermissionEditor = ({ initialPermissions = [], onChange, editable = true,
|
|
|
225
189
|
onChange === null || onChange === void 0 ? void 0 : onChange(modulePermissions);
|
|
226
190
|
};
|
|
227
191
|
return (jsx(Fragment, { children: permissionTags.map((tag) => {
|
|
228
|
-
var _a;
|
|
192
|
+
var _a, _b;
|
|
229
193
|
const isSelected = selectedTags.includes(tag.value);
|
|
230
|
-
return (jsxs("div", { style: { width: '100%', margin: '8px 0' }, className: !editable ? unEditable : '', children: [jsx("span", { style: { fontSize: '16px', fontWeight: 500, marginRight: 8 }, children: tag.
|
|
194
|
+
return (jsxs("div", { style: { width: '100%', margin: '8px 0' }, className: !editable ? unEditable : '', children: [jsx("span", { style: { fontSize: '16px', fontWeight: 500, marginRight: 8 }, children: (_a = texts[PERMISSION_LABEL_KEY[tag.value]]) !== null && _a !== void 0 ? _a : tag.value }), editable && (jsx(Tag.CheckableTag, { checked: isSelected, onChange: (checked) => handleChange(tag.value, checked, tag.readOnly), style: {
|
|
231
195
|
cursor: tag.readOnly ? 'not-allowed' : 'pointer',
|
|
232
196
|
opacity: tag.readOnly ? 0.7 : 1,
|
|
233
197
|
margin: '5px 0',
|
|
@@ -238,14 +202,15 @@ const PermissionEditor = ({ initialPermissions = [], onChange, editable = true,
|
|
|
238
202
|
width: 18,
|
|
239
203
|
border: 0,
|
|
240
204
|
borderRadius: '50%',
|
|
241
|
-
}, className: tag.readOnly ? tagReadonly : '', children: jsx(CheckCircleOutlined, { style: { fontSize: '18px' }, title: isSelected ?
|
|
205
|
+
}, className: tag.readOnly ? tagReadonly : '', children: jsx(CheckCircleOutlined, { style: { fontSize: '18px' }, title: isSelected ? texts.unselectAll : texts.selectAll }) }, tag.value)), jsx(Flex, { gap: 5, wrap: true, align: "center", children: (_b = tag.children) === null || _b === void 0 ? void 0 : _b.map((child) => {
|
|
206
|
+
var _a;
|
|
242
207
|
const isChildSelected = selectedTags.includes(child.value);
|
|
243
208
|
return (jsx(Tag.CheckableTag, { checked: isChildSelected, onChange: (checked) => handleChange(child.value, checked, child.readOnly), style: {
|
|
244
209
|
cursor: child.readOnly ? 'not-allowed' : 'pointer',
|
|
245
210
|
opacity: child.readOnly ? 0.7 : 1,
|
|
246
211
|
margin: '5px 0',
|
|
247
212
|
border: '1px solid #979797',
|
|
248
|
-
}, className: child.readOnly ? tagReadonly : '', children: child.
|
|
213
|
+
}, className: child.readOnly ? tagReadonly : '', children: (_a = texts[PERMISSION_LABEL_KEY[child.value]]) !== null && _a !== void 0 ? _a : child.value }, child.value));
|
|
249
214
|
}) })] }, tag.value));
|
|
250
215
|
}) }));
|
|
251
216
|
};
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { Popover } from 'antd';
|
|
3
3
|
import PermissionEditor from '../permissionEditor/index.js';
|
|
4
|
+
import { useLocale } from '../../../locale/index.js';
|
|
4
5
|
|
|
5
|
-
const PermissionViewPopover = ({ initialPermissions = [], children, title
|
|
6
|
-
|
|
6
|
+
const PermissionViewPopover = ({ initialPermissions = [], children, title, width = 400, }) => {
|
|
7
|
+
const { locale } = useLocale();
|
|
8
|
+
const resolvedTitle = title !== null && title !== void 0 ? title : locale.PermissionEditor.viewTitle;
|
|
9
|
+
return (jsx(Popover, { content: jsx(PermissionEditor, { initialPermissions: initialPermissions, editable: false }), title: resolvedTitle, overlayStyle: { width }, children: children }));
|
|
7
10
|
};
|
|
8
11
|
|
|
9
12
|
export { PermissionViewPopover as default };
|
|
@@ -4,6 +4,7 @@ import { Select, Flex, InputNumber } from 'antd';
|
|
|
4
4
|
import { dataSizeFilter, iconTagHeader, iconTagContent, header, iconClear } from './index.module.scss.js';
|
|
5
5
|
import { MinusOutlined } from '@ant-design/icons';
|
|
6
6
|
import iconTagHeader$1 from '../../assets/icon-tag-header.png.js';
|
|
7
|
+
import { useLocale } from '../../locale/index.js';
|
|
7
8
|
|
|
8
9
|
const { Option } = Select;
|
|
9
10
|
const DATA_SIZE_UNIT = [
|
|
@@ -25,6 +26,8 @@ const transToMB = (value, unit) => {
|
|
|
25
26
|
}
|
|
26
27
|
};
|
|
27
28
|
function DataSizeFilter(p) {
|
|
29
|
+
const { locale } = useLocale();
|
|
30
|
+
const texts = locale.TagGroupFilter;
|
|
28
31
|
const [startValue, setStartValue] = React.useState(null);
|
|
29
32
|
const [startUnit, setStartUnit] = React.useState('kb');
|
|
30
33
|
const [endValue, setEndValue] = React.useState(null);
|
|
@@ -36,10 +39,10 @@ function DataSizeFilter(p) {
|
|
|
36
39
|
if (startValue !== null &&
|
|
37
40
|
endValue !== null &&
|
|
38
41
|
transToMB(startValue, startUnit) > transToMB(endValue, endUnit)) {
|
|
39
|
-
res =
|
|
42
|
+
res = texts.rangeError;
|
|
40
43
|
}
|
|
41
44
|
return res;
|
|
42
|
-
}, [startValue, startUnit, endValue, endUnit,
|
|
45
|
+
}, [startValue, startUnit, endValue, endUnit, texts.rangeError]);
|
|
43
46
|
const handleClear = (e) => {
|
|
44
47
|
e.stopPropagation();
|
|
45
48
|
p.onChange(['', '']);
|
|
@@ -94,7 +97,7 @@ function DataSizeFilter(p) {
|
|
|
94
97
|
setEndValue(p.value[1] ? +p.value[1].slice(0, -2) : null);
|
|
95
98
|
setEndUnit(p.value[1] ? p.value[1].slice(-2) : 'kb');
|
|
96
99
|
}, [p.value]);
|
|
97
|
-
return (jsxs("div", { className: dataSizeFilter, children: [jsx("span", { className: iconTagHeader, style: { backgroundImage: 'url(' + iconTagHeader$1 + ')' } }), jsx("span", { className: iconTagContent }), jsx(Flex, { justify: "space-between", align: "center", className: header, children: jsxs(Flex, { align: "center", children: [jsx("h3", { children:
|
|
100
|
+
return (jsxs("div", { className: dataSizeFilter, children: [jsx("span", { className: iconTagHeader, style: { backgroundImage: 'url(' + iconTagHeader$1 + ')' } }), jsx("span", { className: iconTagContent }), jsx(Flex, { justify: "space-between", align: "center", className: header, children: jsxs(Flex, { align: "center", children: [jsx("h3", { children: texts.dataVolume }), (startValue !== null || endValue !== null) && (jsx("span", { className: iconClear, onClick: handleClear, children: "\uE85E" }))] }) }), jsxs(Fragment, { children: [jsxs(Flex, { align: "center", children: [jsx(InputNumber, { ref: startInputRef, value: startValue, controls: false, placeholder: texts.min, size: "small", style: { fontSize: 12, width: 140 }, addonAfter: jsx(Select, { style: { width: 50 }, popupMatchSelectWidth: false, value: startUnit, onChange: handleStartUnitChange, children: DATA_SIZE_UNIT.map((item, i) => (jsx(Option, { value: item.value, children: item.name }, i))) }), onChange: handleStartValueChange, onPressEnter: handleStartPressEnter, onBlur: handleStartBlur }), jsx(MinusOutlined, { style: { margin: '0 4px' } }), jsx(InputNumber, { ref: endInputRef, value: endValue, controls: false, placeholder: texts.max, size: "small", style: { fontSize: 12, width: 140 }, addonAfter: jsx(Select, { style: { width: 50 }, popupMatchSelectWidth: false, value: endUnit, onChange: handleEndUnitChange, children: DATA_SIZE_UNIT.map((item, i) => (jsx(Option, { value: item.value, children: item.name }, i))) }), onChange: handleEndValueChange, onPressEnter: handleEndPressEnter, onBlur: handleEndBlur })] }), !!errMsg && jsx("div", { style: { color: 'red', marginTop: 4 }, children: errMsg })] })] }));
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
export { DataSizeFilter as default };
|
|
@@ -10,7 +10,7 @@ import { tagGroupFilter } from './index.module.scss.js';
|
|
|
10
10
|
* @param tagSelected 标签选中状态
|
|
11
11
|
* @param needDataSizeFilter 是否需要数据量过滤(可选)
|
|
12
12
|
* @param dataSizeValue 数据量过滤值(可选)
|
|
13
|
-
* @param isEn
|
|
13
|
+
* @param isEn 已废弃,语言由 DataHubProvider / antd ConfigProvider 决定
|
|
14
14
|
* @param tagClassName 标签类名(可选)
|
|
15
15
|
* @param onTagChange 标签选中状态变化回调
|
|
16
16
|
* @param onDataSizeChange 数据量过滤值变化回调(可选)
|
|
@@ -47,7 +47,7 @@ function TagGroupFilter(p) {
|
|
|
47
47
|
React.useEffect(() => {
|
|
48
48
|
setMenuOpenKeys(p.tagGroupDatas.map((item) => item.key));
|
|
49
49
|
}, [p.tagGroupDatas]);
|
|
50
|
-
return (jsx("div", { className: tagGroupFilter, children: viewTagGroupDatas.map((item, index) => (jsx(React.Fragment, { children: item.key === 'dataSize' ? (jsx(DataSizeFilter, {
|
|
50
|
+
return (jsx("div", { className: tagGroupFilter, children: viewTagGroupDatas.map((item, index) => (jsx(React.Fragment, { children: item.key === 'dataSize' ? (jsx(DataSizeFilter, { value: p.dataSizeValue || [], onChange: handleDataSizeChange })) : (jsx(TagFilter, { title: item.title, list: item.children, selected: p.tagSelected[item.key] || [], isFold: !menuOpenKeys.includes(item.key), onChange: (selectd) => handleTagChange(item.key, selectd), onFoldChange: (isFold) => handleOpenKeysChange(item.key, isFold), tagClassName: p.tagClassName }, item.key)) }, index))) }));
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export { TagGroupFilter as default };
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { useState, useRef } from 'react';
|
|
3
3
|
import { IconBold, IconItalic, IconUnderline, IconStrikethrough, IconHighlight, IconCheck, IconTrash, IconLink } from './icons/index.js';
|
|
4
|
+
import { useLocale } from '../../locale/index.js';
|
|
4
5
|
|
|
5
6
|
function TipTapBubbleMenu({ editor }) {
|
|
6
|
-
|
|
7
|
+
const { locale } = useLocale();
|
|
8
|
+
const texts = locale.TipTap;
|
|
9
|
+
return (jsxs("div", { className: "tip-tap-bubble-menu", children: [jsx(BubbleButton, { icon: jsx(IconBold, {}), onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive('bold'), tooltip: texts.bold }), jsx(BubbleButton, { icon: jsx(IconItalic, {}), onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive('italic'), tooltip: texts.italic }), jsx(BubbleButton, { icon: jsx(IconUnderline, {}), onClick: () => editor.chain().focus().toggleUnderline().run(), active: editor.isActive('underline'), tooltip: texts.underline }), jsx(BubbleButton, { icon: jsx(IconStrikethrough, {}), onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive('strike'), tooltip: texts.strike }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsx(BubbleButton, { icon: jsx(IconHighlight, {}), onClick: () => editor.chain().focus().toggleHighlight().run(), active: editor.isActive('highlight'), tooltip: texts.highlightShort }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsx(BubbleLinkButton, { editor: editor })] }));
|
|
7
10
|
}
|
|
8
11
|
function BubbleButton({ icon, onClick, active = false, tooltip, }) {
|
|
9
12
|
return (jsx("button", { className: `tip-tap-btn ${active ? 'tip-tap-btn--active' : ''}`, onClick: onClick, type: "button", title: tooltip, children: icon }));
|
|
10
13
|
}
|
|
11
14
|
function BubbleLinkButton({ editor }) {
|
|
15
|
+
const { locale } = useLocale();
|
|
16
|
+
const texts = locale.TipTap;
|
|
12
17
|
const [showInput, setShowInput] = useState(false);
|
|
13
18
|
const [url, setUrl] = useState('');
|
|
14
19
|
const inputRef = useRef(null);
|
|
@@ -34,14 +39,14 @@ function BubbleLinkButton({ editor }) {
|
|
|
34
39
|
setUrl('');
|
|
35
40
|
}
|
|
36
41
|
if (showInput) {
|
|
37
|
-
return (jsxs("div", { className: "tip-tap-link-popup", style: { boxShadow: 'none', border: 'none', padding: 0, margin: 0 }, children: [jsx("input", { ref: inputRef, type: "text", className: "tip-tap-link-popup__input", style: { width: '160px', padding: '4px 8px', fontSize: '13px' }, placeholder:
|
|
42
|
+
return (jsxs("div", { className: "tip-tap-link-popup", style: { boxShadow: 'none', border: 'none', padding: 0, margin: 0 }, children: [jsx("input", { ref: inputRef, type: "text", className: "tip-tap-link-popup__input", style: { width: '160px', padding: '4px 8px', fontSize: '13px' }, placeholder: texts.linkPlaceholder, value: url, onChange: (e) => setUrl(e.target.value), onKeyDown: (e) => {
|
|
38
43
|
if (e.key === 'Enter')
|
|
39
44
|
handleSubmit();
|
|
40
45
|
if (e.key === 'Escape')
|
|
41
46
|
setShowInput(false);
|
|
42
47
|
} }), jsx("button", { className: "tip-tap-btn", onClick: handleSubmit, type: "button", style: { width: '24px', height: '24px' }, children: jsx(IconCheck, {}) }), editor.isActive('link') && (jsx("button", { className: "tip-tap-btn", onClick: handleRemove, type: "button", style: { width: '24px', height: '24px', color: '#dc2626' }, children: jsx(IconTrash, {}) }))] }));
|
|
43
48
|
}
|
|
44
|
-
return (jsx(BubbleButton, { icon: jsx(IconLink, {}), onClick: handleOpenInput, active: editor.isActive('link'), tooltip:
|
|
49
|
+
return (jsx(BubbleButton, { icon: jsx(IconLink, {}), onClick: handleOpenInput, active: editor.isActive('link'), tooltip: texts.link }));
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
export { TipTapBubbleMenu as default };
|
|
@@ -6,11 +6,14 @@ import { forwardRef, useImperativeHandle } from 'react';
|
|
|
6
6
|
import { editorExtensions } from './extensions/index.js';
|
|
7
7
|
import Toolbar from './toolbar/index.js';
|
|
8
8
|
import TipTapBubbleMenu from './bubble-menu.js';
|
|
9
|
+
import { useLocale } from '../../locale/index.js';
|
|
9
10
|
|
|
10
11
|
useStyle();
|
|
11
|
-
var editor = forwardRef(function TipTapEditor({ content = '', placeholder
|
|
12
|
+
var editor = forwardRef(function TipTapEditor({ content = '', placeholder, editable = true, autofocus = false, className = '', toolbarClassName = '', onChange, }, ref) {
|
|
13
|
+
const { locale } = useLocale();
|
|
14
|
+
const resolvedPlaceholder = placeholder !== null && placeholder !== void 0 ? placeholder : locale.TipTap.placeholder;
|
|
12
15
|
const editor = useEditor({
|
|
13
|
-
extensions: editorExtensions(
|
|
16
|
+
extensions: editorExtensions(resolvedPlaceholder),
|
|
14
17
|
content,
|
|
15
18
|
editable,
|
|
16
19
|
autofocus,
|
|
@@ -2,8 +2,10 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useEditorState } from '@tiptap/react';
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { IconBold, IconHighlight } from '../../icons/index.js';
|
|
5
|
+
import { useLocale } from '../../../../locale/index.js';
|
|
5
6
|
|
|
6
7
|
function ColorPicker({ editor, type, tooltip }) {
|
|
8
|
+
const { locale } = useLocale();
|
|
7
9
|
const [isOpen, setIsOpen] = useState(false);
|
|
8
10
|
const dropdownRef = useRef(null);
|
|
9
11
|
const colors = [
|
|
@@ -70,7 +72,7 @@ function ColorPicker({ editor, type, tooltip }) {
|
|
|
70
72
|
}
|
|
71
73
|
setIsOpen(false);
|
|
72
74
|
}
|
|
73
|
-
return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-btn ${(editorState === null || editorState === void 0 ? void 0 : editorState.isActive) ? 'tip-tap-btn--active' : ''}`, onClick: () => setIsOpen(!isOpen), type: "button", style: type === 'textColor' && (editorState === null || editorState === void 0 ? void 0 : editorState.color) ? { color: editorState.color } : {}, children: [type === 'textColor' ? (jsx(IconBold, { style: { borderBottom: `3px solid ${(editorState === null || editorState === void 0 ? void 0 : editorState.color) || '#000'}` } })) : (jsx(IconHighlight, {})), jsx("span", { className: "tip-tap-tooltip", children: tooltip })] }), jsx("div", { className: "tip-tap-dropdown__menu", children: jsxs("div", { className: "tip-tap-color-picker", children: [jsx("button", { className: "tip-tap-color-picker__swatch tip-tap-color-picker__swatch--reset", onClick: () => handleColorSelect(null), title:
|
|
75
|
+
return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-btn ${(editorState === null || editorState === void 0 ? void 0 : editorState.isActive) ? 'tip-tap-btn--active' : ''}`, onClick: () => setIsOpen(!isOpen), type: "button", style: type === 'textColor' && (editorState === null || editorState === void 0 ? void 0 : editorState.color) ? { color: editorState.color } : {}, children: [type === 'textColor' ? (jsx(IconBold, { style: { borderBottom: `3px solid ${(editorState === null || editorState === void 0 ? void 0 : editorState.color) || '#000'}` } })) : (jsx(IconHighlight, {})), jsx("span", { className: "tip-tap-tooltip", children: tooltip })] }), jsx("div", { className: "tip-tap-dropdown__menu", children: jsxs("div", { className: "tip-tap-color-picker", children: [jsx("button", { className: "tip-tap-color-picker__swatch tip-tap-color-picker__swatch--reset", onClick: () => handleColorSelect(null), title: locale.TipTap.removeColor, type: "button" }), colors.map((color) => (jsx("button", { className: "tip-tap-color-picker__swatch", style: { background: color }, onClick: () => handleColorSelect(color), type: "button" }, color)))] }) })] }));
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
export { ColorPicker };
|
|
@@ -2,15 +2,18 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useEditorState } from '@tiptap/react';
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { IconParagraph, IconH1, IconH2, IconH3, IconChevronDown } from '../../icons/index.js';
|
|
5
|
+
import { useLocale } from '../../../../locale/index.js';
|
|
5
6
|
|
|
6
7
|
function HeadingDropdown({ editor }) {
|
|
8
|
+
const { locale } = useLocale();
|
|
9
|
+
const texts = locale.TipTap;
|
|
7
10
|
const [isOpen, setIsOpen] = useState(false);
|
|
8
11
|
const dropdownRef = useRef(null);
|
|
9
12
|
const headings = [
|
|
10
|
-
{ level: 0, label:
|
|
11
|
-
{ level: 1, label:
|
|
12
|
-
{ level: 2, label:
|
|
13
|
-
{ level: 3, label:
|
|
13
|
+
{ level: 0, label: texts.paragraph, icon: jsx(IconParagraph, {}) },
|
|
14
|
+
{ level: 1, label: texts.heading1, icon: jsx(IconH1, {}) },
|
|
15
|
+
{ level: 2, label: texts.heading2, icon: jsx(IconH2, {}) },
|
|
16
|
+
{ level: 3, label: texts.heading3, icon: jsx(IconH3, {}) },
|
|
14
17
|
];
|
|
15
18
|
// 使用 useEditorState 来同步编辑器状态
|
|
16
19
|
const editorState = useEditorState({
|
|
@@ -38,7 +41,7 @@ function HeadingDropdown({ editor }) {
|
|
|
38
41
|
}
|
|
39
42
|
setIsOpen(false);
|
|
40
43
|
}
|
|
41
|
-
return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-dropdown__trigger ${editorState && editorState.level !== 0 ? 'tip-tap-dropdown__trigger--active' : ''}`, onClick: () => setIsOpen(!isOpen), type: "button", children: [(editorState === null || editorState === void 0 ? void 0 : editorState.icon) || jsx(IconParagraph, {}), jsx("span", { children: (editorState === null || editorState === void 0 ? void 0 : editorState.label) ||
|
|
44
|
+
return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-dropdown__trigger ${editorState && editorState.level !== 0 ? 'tip-tap-dropdown__trigger--active' : ''}`, onClick: () => setIsOpen(!isOpen), type: "button", children: [(editorState === null || editorState === void 0 ? void 0 : editorState.icon) || jsx(IconParagraph, {}), jsx("span", { children: (editorState === null || editorState === void 0 ? void 0 : editorState.label) || texts.paragraph }), jsx(IconChevronDown, { className: "tip-tap-dropdown__arrow" })] }), jsx("div", { className: "tip-tap-dropdown__menu", children: headings.map(({ level, label, icon }) => (jsxs("button", { className: `tip-tap-dropdown__item ${(editorState === null || editorState === void 0 ? void 0 : editorState.level) === level ? 'tip-tap-dropdown__item--active' : ''}`, onClick: () => handleSelect(level), type: "button", children: [jsx("span", { className: "tip-tap-dropdown__item-icon", children: icon }), label] }, level))) })] }));
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
export { HeadingDropdown };
|
|
@@ -3,8 +3,11 @@ import { useEditorState } from '@tiptap/react';
|
|
|
3
3
|
import { getMarkRange } from '@tiptap/core';
|
|
4
4
|
import { useState, useRef, useEffect } from 'react';
|
|
5
5
|
import { IconLink, IconCheck, IconTrash } from '../../icons/index.js';
|
|
6
|
+
import { useLocale } from '../../../../locale/index.js';
|
|
6
7
|
|
|
7
8
|
function LinkButton({ editor }) {
|
|
9
|
+
const { locale } = useLocale();
|
|
10
|
+
const texts = locale.TipTap;
|
|
8
11
|
const [isOpen, setIsOpen] = useState(false);
|
|
9
12
|
const [label, setLabel] = useState('');
|
|
10
13
|
const [url, setUrl] = useState('');
|
|
@@ -101,7 +104,7 @@ function LinkButton({ editor }) {
|
|
|
101
104
|
setLabel('');
|
|
102
105
|
setUrl('');
|
|
103
106
|
}
|
|
104
|
-
return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-btn ${(editorState === null || editorState === void 0 ? void 0 : editorState.isActive) ? 'tip-tap-btn--active' : ''}`, onClick: handleToggleOpen, type: "button", children: [jsx(IconLink, {}), jsx("span", { className: "tip-tap-tooltip", children:
|
|
107
|
+
return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-btn ${(editorState === null || editorState === void 0 ? void 0 : editorState.isActive) ? 'tip-tap-btn--active' : ''}`, onClick: handleToggleOpen, type: "button", children: [jsx(IconLink, {}), jsx("span", { className: "tip-tap-tooltip", children: texts.link })] }), jsx("div", { className: "tip-tap-dropdown__menu", style: { width: 'auto', padding: 0 }, children: jsxs("div", { className: "tip-tap-link-popup", style: { flexDirection: 'column', alignItems: 'stretch' }, children: [jsx("input", { ref: labelInputRef, type: "text", className: "tip-tap-link-popup__input", placeholder: texts.linkText, value: label, onChange: (e) => setLabel(e.target.value), onKeyDown: (e) => e.key === 'Enter' && handleSubmit(), style: { marginBottom: '8px' } }), jsx("input", { type: "text", className: "tip-tap-link-popup__input", placeholder: texts.linkUrl, value: url, onChange: (e) => setUrl(e.target.value), onKeyDown: (e) => e.key === 'Enter' && handleSubmit() }), jsxs("div", { style: { display: 'flex', gap: '4px', marginTop: '8px' }, children: [jsx("button", { className: "tip-tap-link-popup__btn", onClick: handleSubmit, type: "button", children: jsx(IconCheck, {}) }), (editorState === null || editorState === void 0 ? void 0 : editorState.isActive) && (jsx("button", { className: "tip-tap-link-popup__btn tip-tap-link-popup__btn--danger", onClick: handleRemove, type: "button", children: jsx(IconTrash, {}) }))] })] }) })] }));
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
export { LinkButton };
|
|
@@ -2,8 +2,11 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useEditorState } from '@tiptap/react';
|
|
3
3
|
import { useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { IconTable } from '../../icons/index.js';
|
|
5
|
+
import { useLocale } from '../../../../locale/index.js';
|
|
5
6
|
|
|
6
7
|
function TableButton({ editor }) {
|
|
8
|
+
const { locale } = useLocale();
|
|
9
|
+
const texts = locale.TipTap;
|
|
7
10
|
const [isOpen, setIsOpen] = useState(false);
|
|
8
11
|
const [hoveredCell, setHoveredCell] = useState({ row: 0, col: 0 });
|
|
9
12
|
const dropdownRef = useRef(null);
|
|
@@ -27,11 +30,11 @@ function TableButton({ editor }) {
|
|
|
27
30
|
editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
|
|
28
31
|
setIsOpen(false);
|
|
29
32
|
}
|
|
30
|
-
return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-btn ${(editorState === null || editorState === void 0 ? void 0 : editorState.isActive) ? 'tip-tap-btn--active' : ''}`, onClick: () => setIsOpen(!isOpen), type: "button", children: [jsx(IconTable, {}), jsx("span", { className: "tip-tap-tooltip", children:
|
|
33
|
+
return (jsxs("div", { className: `tip-tap-dropdown ${isOpen ? 'tip-tap-dropdown--open' : ''}`, ref: dropdownRef, children: [jsxs("button", { className: `tip-tap-btn ${(editorState === null || editorState === void 0 ? void 0 : editorState.isActive) ? 'tip-tap-btn--active' : ''}`, onClick: () => setIsOpen(!isOpen), type: "button", children: [jsx(IconTable, {}), jsx("span", { className: "tip-tap-tooltip", children: texts.insertTable })] }), jsx("div", { className: "tip-tap-dropdown__menu", style: { padding: 0 }, children: jsxs("div", { className: "tip-tap-table-menu", children: [jsx("div", { className: "tip-tap-table-menu__label", children: texts.selectTableSize }), jsx("div", { className: "tip-tap-table-menu__grid", children: Array.from({ length: 36 }, (_, i) => {
|
|
31
34
|
const row = Math.floor(i / 6) + 1;
|
|
32
35
|
const col = (i % 6) + 1;
|
|
33
36
|
return (jsx("button", { className: `tip-tap-table-menu__cell ${row <= hoveredCell.row && col <= hoveredCell.col ? 'tip-tap-table-menu__cell--active' : ''}`, onMouseEnter: () => setHoveredCell({ row, col }), onClick: () => handleInsertTable(row, col), type: "button" }, i));
|
|
34
|
-
}) }), jsx("div", { className: "tip-tap-table-menu__size", children: hoveredCell.row > 0 ? `${hoveredCell.row} × ${hoveredCell.col}` :
|
|
37
|
+
}) }), jsx("div", { className: "tip-tap-table-menu__size", children: hoveredCell.row > 0 ? `${hoveredCell.row} × ${hoveredCell.col}` : texts.selectSize })] }) })] }));
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
export { TableButton };
|
|
@@ -7,8 +7,11 @@ import { ColorPicker } from './components/color-picker.js';
|
|
|
7
7
|
import { LinkButton } from './components/link-button.js';
|
|
8
8
|
import { ImageButton } from './components/image-button.js';
|
|
9
9
|
import { TableButton } from './components/table-button.js';
|
|
10
|
+
import { useLocale } from '../../../locale/index.js';
|
|
10
11
|
|
|
11
12
|
function Toolbar({ editor, className = '' }) {
|
|
13
|
+
const { locale } = useLocale();
|
|
14
|
+
const texts = locale.TipTap;
|
|
12
15
|
// 使用 useEditorState 来同步编辑器状态
|
|
13
16
|
const editorState = useEditorState({
|
|
14
17
|
editor,
|
|
@@ -33,7 +36,7 @@ function Toolbar({ editor, className = '' }) {
|
|
|
33
36
|
canRedo: ctx.editor.can().redo(),
|
|
34
37
|
}),
|
|
35
38
|
});
|
|
36
|
-
return (jsxs("div", { className: `tip-tap-toolbar ${className}`, children: [jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconUndo, {}), tooltip:
|
|
39
|
+
return (jsxs("div", { className: `tip-tap-toolbar ${className}`, children: [jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconUndo, {}), tooltip: texts.undo, onClick: () => editor.chain().focus().undo().run(), disabled: !(editorState === null || editorState === void 0 ? void 0 : editorState.canUndo) }), jsx(ToolbarButton, { icon: jsx(IconRedo, {}), tooltip: texts.redo, onClick: () => editor.chain().focus().redo().run(), disabled: !(editorState === null || editorState === void 0 ? void 0 : editorState.canRedo) })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconBold, {}), tooltip: texts.bold, onClick: () => editor.chain().focus().toggleBold().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isBold }), jsx(ToolbarButton, { icon: jsx(IconItalic, {}), tooltip: texts.italic, onClick: () => editor.chain().focus().toggleItalic().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isItalic }), jsx(ToolbarButton, { icon: jsx(IconUnderline, {}), tooltip: texts.underline, onClick: () => editor.chain().focus().toggleUnderline().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isUnderline }), jsx(ToolbarButton, { icon: jsx(IconStrikethrough, {}), tooltip: texts.strike, onClick: () => editor.chain().focus().toggleStrike().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isStrike })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsx(HeadingDropdown, { editor: editor }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ColorPicker, { editor: editor, type: "textColor", tooltip: texts.textColor }), jsx(ColorPicker, { editor: editor, type: "highlight", tooltip: texts.highlight })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconAlignLeft, {}), tooltip: texts.alignLeft, onClick: () => editor.chain().focus().setTextAlign('left').run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isAlignLeft }), jsx(ToolbarButton, { icon: jsx(IconAlignCenter, {}), tooltip: texts.alignCenter, onClick: () => editor.chain().focus().setTextAlign('center').run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isAlignCenter }), jsx(ToolbarButton, { icon: jsx(IconAlignRight, {}), tooltip: texts.alignRight, onClick: () => editor.chain().focus().setTextAlign('right').run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isAlignRight })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconListBullet, {}), tooltip: texts.bulletList, onClick: () => editor.chain().focus().toggleBulletList().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isBulletList }), jsx(ToolbarButton, { icon: jsx(IconListNumbered, {}), tooltip: texts.orderedList, onClick: () => editor.chain().focus().toggleOrderedList().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isOrderedList })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(ToolbarButton, { icon: jsx(IconQuote, {}), tooltip: texts.quote, onClick: () => editor.chain().focus().toggleBlockquote().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isBlockquote }), jsx(ToolbarButton, { icon: jsx(IconCode, {}), tooltip: texts.codeBlock, onClick: () => editor.chain().focus().toggleCodeBlock().run(), active: editorState === null || editorState === void 0 ? void 0 : editorState.isCodeBlock }), jsx(ToolbarButton, { icon: jsx(IconMinus, {}), tooltip: texts.divider, onClick: () => editor.chain().focus().setHorizontalRule().run() })] }), jsx("div", { className: "tip-tap-toolbar__divider" }), jsxs("div", { className: "tip-tap-toolbar__group", children: [jsx(LinkButton, { editor: editor }), jsx(ImageButton, { editor: editor }), jsx(TableButton, { editor: editor })] })] }));
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
export { Toolbar as default };
|
|
@@ -11,9 +11,13 @@ import { useFormatFiles } from './hooks/useFormatFiles.js';
|
|
|
11
11
|
import { useUploadFileToOSS } from './hooks/useUploadFileToOSS.js';
|
|
12
12
|
import { useResumeUnfinishedUploads } from './hooks/useResumeUnfinishedUploads.js';
|
|
13
13
|
import { FileUploadDrawerContext } from './index.js';
|
|
14
|
+
import { useLocale } from '../../locale/index.js';
|
|
14
15
|
|
|
15
|
-
function FileUploadDrawer({ open, identifier, accept, dragAreaDescription, footer, title
|
|
16
|
+
function FileUploadDrawer({ open, identifier, accept, dragAreaDescription, footer, title, showFinished = false, directory = false, onClose, }) {
|
|
16
17
|
var _a, _b;
|
|
18
|
+
const { locale, t } = useLocale();
|
|
19
|
+
const texts = locale.UploadDrawer;
|
|
20
|
+
const resolvedTitle = title !== null && title !== void 0 ? title : texts.title;
|
|
17
21
|
const uploadStore = useContext(UploadStoreContext);
|
|
18
22
|
const setUploadsStore = useContext(UploadStoreDispatchContext);
|
|
19
23
|
const { onSuccess } = useContext(FileUploadDrawerContext);
|
|
@@ -47,7 +51,7 @@ function FileUploadDrawer({ open, identifier, accept, dragAreaDescription, foote
|
|
|
47
51
|
uploadFileToOSS(fileToUpload, onSuccess);
|
|
48
52
|
}
|
|
49
53
|
}, [identifier, onSuccess, uploadFileToOSS, uploadStore]);
|
|
50
|
-
return (jsxs(Drawer, { className: "mylib-upload-drawer", open: open, title:
|
|
54
|
+
return (jsxs(Drawer, { className: "mylib-upload-drawer", open: open, title: resolvedTitle, width: 480, onClose: onClose, footer: footer, children: [jsx(FileUploadDrawerFileDragger, { directory: directory, accept: accept, dragAreaDescription: dragAreaDescription, onFileReceived: onFileReceived }), raws.length === 0 && ((_a = uploadStore[identifier]) === null || _a === void 0 ? void 0 : _a.length) === 0 && (jsx(Empty, { className: "mt-20", description: texts.empty })), raws.length > 0 && (jsxs("div", { className: "flex justify-center gap-4 mt-4", children: [jsx(LoadingOutlined, {}), t(texts.prechecking, { count: raws.length })] })), ((_b = uploadStore[identifier]) === null || _b === void 0 ? void 0 : _b.length) > 0 && (jsx(FileUploading, { showFinished: showFinished, identifier: identifier }))] }));
|
|
51
55
|
function onFileReceived(files) {
|
|
52
56
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53
57
|
setRaws((prev) => [...prev, ...files]);
|
|
@@ -8,6 +8,7 @@ import FileUploadDrawerListProgressButton from './fileUploadDrawerListProgressBu
|
|
|
8
8
|
import { Flex, Button } from 'antd';
|
|
9
9
|
import { useRetryUpload } from './hooks/useRetryUpload.js';
|
|
10
10
|
import { useCancelUpload } from './hooks/useCancelUpload.js';
|
|
11
|
+
import { useLocale } from '../../locale/index.js';
|
|
11
12
|
|
|
12
13
|
function FileUploading({ identifier, showFinished, }) {
|
|
13
14
|
const uploadContext = useContext(UploadStoreContext);
|
|
@@ -38,9 +39,11 @@ function FileUploading({ identifier, showFinished, }) {
|
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
function FileListItem({ identifier, file, showFinished, onButtonClick }) {
|
|
42
|
+
const { locale } = useLocale();
|
|
43
|
+
const texts = locale.UploadDrawer;
|
|
41
44
|
const setUploadsStore = useContext(UploadStoreDispatchContext);
|
|
42
45
|
const showDelete = typeof showFinished === 'object' && showFinished.withDelete;
|
|
43
|
-
return (jsx("div", { className: "mb-2 last:mb-0", children: jsxs("div", { className: "px-4 my-2 relative flex justify-between items-center", children: [jsxs(Flex, { align: "center", gap: ".5rem", title: file.fileName, children: [jsx(FileTextOutlined, {}), jsx("span", { className: "truncate w-40", children: file.fileName })] }), jsxs(Flex, { align: "center", gap: ".5rem", children: [jsx(FileUploadDrawerListProgressButton, { status: file.fileStatus, percent: Number(file.percentage.toFixed(0)), onClick: () => onButtonClick(file) }), file.fileStatus === FILE_UPLOAD_STATUS.FINISHED && showDelete && (jsx(Button, { type: "text", size: "large", className: "px-3", disabled: showDelete.disabled, title:
|
|
46
|
+
return (jsx("div", { className: "mb-2 last:mb-0", children: jsxs("div", { className: "px-4 my-2 relative flex justify-between items-center", children: [jsxs(Flex, { align: "center", gap: ".5rem", title: file.fileName, children: [jsx(FileTextOutlined, {}), jsx("span", { className: "truncate w-40", children: file.fileName })] }), jsxs(Flex, { align: "center", gap: ".5rem", children: [jsx(FileUploadDrawerListProgressButton, { status: file.fileStatus, percent: Number(file.percentage.toFixed(0)), onClick: () => onButtonClick(file) }), file.fileStatus === FILE_UPLOAD_STATUS.FINISHED && showDelete && (jsx(Button, { type: "text", size: "large", className: "px-3", disabled: showDelete.disabled, title: showDelete.disabled ? texts.removeDisabled : texts.remove, onClick: () => onDelete(file, showDelete.onDelete), children: jsx(DeleteOutlined, {}) }))] })] }) }));
|
|
44
47
|
function onDelete(file, onDeleteImpl) {
|
|
45
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
46
49
|
const result = yield onDeleteImpl(file.fileName);
|
|
@@ -5,6 +5,7 @@ import { useState } from 'react';
|
|
|
5
5
|
import { FILE_UPLOAD_STATUS } from './utils/constant.js';
|
|
6
6
|
import 'tslib';
|
|
7
7
|
import { useProgressButtonRef } from './hooks/useProgressButtonRef.js';
|
|
8
|
+
import { useLocale } from '../../locale/index.js';
|
|
8
9
|
|
|
9
10
|
// 进度条样式属性
|
|
10
11
|
const progressStyleProps = {
|
|
@@ -14,7 +15,8 @@ const progressStyleProps = {
|
|
|
14
15
|
strokeLinecap: 'butt',
|
|
15
16
|
};
|
|
16
17
|
function FileUploadDrawerListProgressButton({ percent, status, onClick, }) {
|
|
17
|
-
|
|
18
|
+
const { locale } = useLocale();
|
|
19
|
+
const texts = locale.UploadDrawer;
|
|
18
20
|
const { progressButtonRef, buttonInHover } = useProgressButtonRef();
|
|
19
21
|
// 状态用于跟踪是否正在取消上传
|
|
20
22
|
const [isCanceling, setIsCanceling] = useState(false);
|
|
@@ -31,7 +33,7 @@ function FileUploadDrawerListProgressButton({ percent, status, onClick, }) {
|
|
|
31
33
|
} })) }));
|
|
32
34
|
}
|
|
33
35
|
// 默认情况下显示进度按钮
|
|
34
|
-
return (jsx(Button, { type: "text", shape: "circle", disabled: isCanceling, ref: progressButtonRef, title: status === FILE_UPLOAD_STATUS.PAUSED ?
|
|
36
|
+
return (jsx(Button, { type: "text", shape: "circle", disabled: isCanceling, ref: progressButtonRef, title: status === FILE_UPLOAD_STATUS.PAUSED ? texts.continue : texts.cancelDownload, onClick: () => {
|
|
35
37
|
onClick();
|
|
36
38
|
if (status === FILE_UPLOAD_STATUS.UPLOADING) {
|
|
37
39
|
setIsCanceling(true);
|
|
@@ -5,9 +5,11 @@ import { useContext } from 'react';
|
|
|
5
5
|
import { UploadStoreDispatchContext } from '../UploadStoreProvider.js';
|
|
6
6
|
import { App } from 'antd';
|
|
7
7
|
import { FileUploadDrawerContext } from '../index.js';
|
|
8
|
+
import { useLocale } from '../../../locale/index.js';
|
|
8
9
|
|
|
9
10
|
function useCancelUpload() {
|
|
10
11
|
const { message } = App.useApp();
|
|
12
|
+
const { locale } = useLocale();
|
|
11
13
|
const { identifier, onCancelUpload } = useContext(FileUploadDrawerContext);
|
|
12
14
|
const uploadsDispatch = useContext(UploadStoreDispatchContext);
|
|
13
15
|
return function cancelUpload(file) {
|
|
@@ -22,7 +24,7 @@ function useCancelUpload() {
|
|
|
22
24
|
deleteFile(file);
|
|
23
25
|
}
|
|
24
26
|
else {
|
|
25
|
-
message.error(result.reason ||
|
|
27
|
+
message.error(result.reason || locale.UploadDrawer.cancelFailed);
|
|
26
28
|
}
|
|
27
29
|
});
|
|
28
30
|
};
|