@douyinfe/semi-foundation 2.89.2-alpha.3 → 2.90.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/aiChatInput/aiChatInput.scss +1 -0
- package/aiChatInput/constants.ts +5 -1
- package/aiChatInput/foundation.ts +4 -3
- package/chat/inputboxFoundation.ts +6 -1
- package/getBabelConfig.js +24 -0
- package/gulpfile.js +107 -0
- package/jsonViewer/script/build.js +51 -0
- package/lib/cjs/aiChatInput/aiChatInput.css +1 -0
- package/lib/cjs/aiChatInput/aiChatInput.scss +1 -0
- package/lib/cjs/aiChatInput/constants.d.ts +4 -0
- package/lib/cjs/aiChatInput/constants.js +5 -1
- package/lib/cjs/aiChatInput/foundation.js +5 -2
- package/lib/cjs/chat/inputboxFoundation.js +7 -1
- package/lib/cjs/tagInput/foundation.d.ts +1 -0
- package/lib/cjs/tagInput/foundation.js +13 -4
- package/lib/es/aiChatInput/aiChatInput.css +1 -0
- package/lib/es/aiChatInput/aiChatInput.scss +1 -0
- package/lib/es/aiChatInput/constants.d.ts +4 -0
- package/lib/es/aiChatInput/constants.js +5 -1
- package/lib/es/aiChatInput/foundation.js +6 -3
- package/lib/es/chat/inputboxFoundation.js +7 -1
- package/lib/es/tagInput/foundation.d.ts +1 -0
- package/lib/es/tagInput/foundation.js +13 -4
- package/package.json +5 -22
- package/scripts/compileLib.js +13 -0
- package/tagInput/foundation.ts +12 -4
- package/tsconfig.json +25 -0
|
@@ -523,6 +523,7 @@ $module: #{$prefix}-aiChatInput;
|
|
|
523
523
|
|
|
524
524
|
.input-slot {
|
|
525
525
|
display: inline-block;
|
|
526
|
+
box-sizing: content-box;
|
|
526
527
|
background-color: $color-aiChatInput_rich_text-input_slot-bg;
|
|
527
528
|
border-radius: $radius-aiChatInput_rich_text-input_slot;
|
|
528
529
|
padding: $spacing-aiChatInput_rich_text-input_slot-paddingY $spacing-aiChatInput_rich_text-input_slot-paddingX;
|
package/aiChatInput/constants.ts
CHANGED
|
@@ -10,7 +10,11 @@ const strings = {
|
|
|
10
10
|
ZERO_WIDTH_CHAR: '\uFEFF',
|
|
11
11
|
PIC_PREFIX: 'image/',
|
|
12
12
|
PIC_SUFFIX_ARRAY: ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'],
|
|
13
|
-
DELETABLE: 'skipCustomTransactionPlugin'
|
|
13
|
+
DELETABLE: 'skipCustomTransactionPlugin',
|
|
14
|
+
SEND_HOTKEY: {
|
|
15
|
+
'ENTER': 'enter' as const,
|
|
16
|
+
'SHIFT_ENTER': 'shift+enter' as const,
|
|
17
|
+
}
|
|
14
18
|
};
|
|
15
19
|
|
|
16
20
|
const numbers = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import BaseFoundation, { DefaultAdapter } from '../base/foundation';
|
|
2
2
|
import { Attachment, BaseSkill, Suggestion, Reference, Content, LeftMenuChangeProps, MessageContent } from './interface';
|
|
3
3
|
import { get, isNumber, isString } from 'lodash';
|
|
4
|
-
import { cssClasses } from './constants';
|
|
4
|
+
import { cssClasses, strings } from './constants';
|
|
5
5
|
import { findSkillSlotInString, getSkillSlotString, transformJSONResult } from './utils';
|
|
6
6
|
|
|
7
7
|
export interface AIChatInputAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
|
|
@@ -338,6 +338,7 @@ export default class AIChatInputFoundation extends BaseFoundation<AIChatInputAda
|
|
|
338
338
|
|
|
339
339
|
handRichTextArealKeyDown = (view: any, event: KeyboardEvent) => {
|
|
340
340
|
// console.log('outer key down handle');
|
|
341
|
+
const { sendHotKey } = this.getProps();
|
|
341
342
|
const { suggestionVisible, skillVisible } = this.getStates();
|
|
342
343
|
/**
|
|
343
344
|
* 当建议/技能面板可见时候,上下按键,enter 按键被用于操作面板选项的 active 项,或做选中操作的,
|
|
@@ -351,11 +352,11 @@ export default class AIChatInputFoundation extends BaseFoundation<AIChatInputAda
|
|
|
351
352
|
}
|
|
352
353
|
const editor = this._adapter.getEditor() ?? {};
|
|
353
354
|
const allowHotKeySend = get(editor, 'storage.SemiAIChatInput.allowHotKeySend');
|
|
354
|
-
if (event.key === 'Enter' && !event.shiftKey && allowHotKeySend) {
|
|
355
|
+
if (event.key === 'Enter' && (sendHotKey === strings.SEND_HOTKEY.ENTER ? !event.shiftKey : event.shiftKey) && allowHotKeySend) {
|
|
355
356
|
this.handleSend();
|
|
356
357
|
return true;
|
|
357
358
|
}
|
|
358
|
-
if (event.key === 'Enter' && event.shiftKey) {
|
|
359
|
+
if (event.key === 'Enter' && (sendHotKey === strings.SEND_HOTKEY.ENTER ? event.shiftKey : !event.shiftKey)) {
|
|
359
360
|
/**
|
|
360
361
|
* Tiptap 默认情况下 Enter + Shift 时候是使用 <br /> 实现换行
|
|
361
362
|
* 为保证自定义的一些逻辑生效(比如零宽字符的插入),Enter + Shift 希望实现通过新建 p 标签的方式完成换行
|
|
@@ -60,7 +60,12 @@ export default class InputBoxFoundation <P = Record<string, any>, S = Record<str
|
|
|
60
60
|
|
|
61
61
|
getDisableSend = () => {
|
|
62
62
|
const { content, attachment } = this.getStates();
|
|
63
|
-
const { disableSend: disableSendInProps } = this.getProps();
|
|
63
|
+
const { disableSend: disableSendInProps, canSend } = this.getProps();
|
|
64
|
+
// 如果用户设置了 canSend API,则使用 canSend 值
|
|
65
|
+
// If the user has configured the canSend API, then the canSend value will be used.
|
|
66
|
+
if (typeof canSend === 'boolean') {
|
|
67
|
+
return !canSend;
|
|
68
|
+
}
|
|
64
69
|
/** 不能发送的条件:(满足任1)
|
|
65
70
|
* 1. props 中禁止发送;2. 没有文本输入,且没有上传文件; 3.上传文件中有状态不为 success 的
|
|
66
71
|
* Conditions under which content cannot be sent: (any one of the following conditions must be met)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module.exports = ({ isESM }) => {
|
|
2
|
+
return {
|
|
3
|
+
presets: [
|
|
4
|
+
[
|
|
5
|
+
'@babel/preset-env',
|
|
6
|
+
{
|
|
7
|
+
modules: isESM ? false : 'commonjs',
|
|
8
|
+
targets: {
|
|
9
|
+
browsers: [
|
|
10
|
+
"> 0.5%",
|
|
11
|
+
"last 2 versions",
|
|
12
|
+
"Firefox ESR",
|
|
13
|
+
"not dead",
|
|
14
|
+
"not IE 11"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
],
|
|
20
|
+
plugins: [
|
|
21
|
+
'lodash',
|
|
22
|
+
]
|
|
23
|
+
};
|
|
24
|
+
};
|
package/gulpfile.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { Buffer } = require('buffer');
|
|
3
|
+
const through2 = require('through2');
|
|
4
|
+
const gulp = require('gulp');
|
|
5
|
+
const merge2 = require('merge2');
|
|
6
|
+
const gulpTS = require('gulp-typescript');
|
|
7
|
+
const gulpBabel = require('gulp-babel');
|
|
8
|
+
const sass = require('gulp-sass')(require('sass'));
|
|
9
|
+
const del = require('del');
|
|
10
|
+
const tsConfig = require('./tsconfig.json');
|
|
11
|
+
const getBabelConfig = require('./getBabelConfig');
|
|
12
|
+
|
|
13
|
+
gulp.task('cleanLib', function cleanLib() {
|
|
14
|
+
return del(['lib/**/*']);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function compileTS(isESM) {
|
|
18
|
+
const targetDir = isESM ? 'lib/es' : 'lib/cjs';
|
|
19
|
+
const tsStream = gulp.src(['**/*.ts', '!node_modules/**/*.*'])
|
|
20
|
+
.pipe(gulpTS(tsConfig.compilerOptions));
|
|
21
|
+
const jsStream = tsStream.js
|
|
22
|
+
.pipe(gulpBabel(getBabelConfig({ isESM })))
|
|
23
|
+
.pipe(gulp.dest(targetDir));
|
|
24
|
+
const dtsStream = tsStream.dts.pipe(gulp.dest(targetDir));
|
|
25
|
+
return merge2([jsStream, dtsStream]);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
gulp.task('compileTSForESM', function compileTSForESM() {
|
|
29
|
+
return compileTS(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
gulp.task('compileTSForCJS', function compileTSForCJS() {
|
|
33
|
+
return compileTS(false);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const excludeScss = [
|
|
37
|
+
'!**/button/splitButtonGroup.scss',
|
|
38
|
+
'!**/steps/bacisSteps.scss',
|
|
39
|
+
'!**/steps/fillSteps.scss',
|
|
40
|
+
'!**/steps/navSteps.scss',
|
|
41
|
+
'!**/table/operationPanel.scss',
|
|
42
|
+
'!**/tooltip/arrow.scss',
|
|
43
|
+
'!**/autoComplete/option.scss',
|
|
44
|
+
'!**/select/option.scss',
|
|
45
|
+
];
|
|
46
|
+
gulp.task('compileScss', function compileScss() {
|
|
47
|
+
return gulp.src(['**/*.scss', '!node_modules/**/*.*', '!**/rtl.scss', '!**/variables.scss', "!**/animation.scss", ...excludeScss])
|
|
48
|
+
.pipe(through2.obj(
|
|
49
|
+
function (chunk, enc, cb) {
|
|
50
|
+
const rootPath = path.join(__dirname, '../../');
|
|
51
|
+
const scssVarStr = `@import "${rootPath}/packages/semi-theme-default/scss/index.scss";\n`;
|
|
52
|
+
let scssRaw = chunk.contents.toString('utf-8');
|
|
53
|
+
if (scssRaw.startsWith("@use")) {
|
|
54
|
+
const scssRawSplit = scssRaw.split("\n");
|
|
55
|
+
const codeStartIndex = scssRawSplit.findIndex(item => !item.startsWith("@use"));
|
|
56
|
+
scssRawSplit.splice(codeStartIndex, 0, scssVarStr);
|
|
57
|
+
scssRaw = scssRawSplit.join("\n");
|
|
58
|
+
} else {
|
|
59
|
+
scssRaw = `${scssVarStr}\n${scssRaw}`;
|
|
60
|
+
}
|
|
61
|
+
chunk.contents = Buffer.from(scssRaw, 'utf-8');
|
|
62
|
+
cb(null, chunk);
|
|
63
|
+
}
|
|
64
|
+
))
|
|
65
|
+
.pipe(sass({
|
|
66
|
+
charset: false
|
|
67
|
+
}).on('error', sass.logError))
|
|
68
|
+
.pipe(gulp.dest('lib/es'))
|
|
69
|
+
.pipe(gulp.dest('lib/cjs'));
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
gulp.task('moveScss', function moveScss() {
|
|
73
|
+
return gulp.src(['**/*.scss', '!node_modules/**/*.*'])
|
|
74
|
+
.pipe(gulp.dest('lib/es'))
|
|
75
|
+
.pipe(gulp.dest('lib/cjs'));
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
gulp.task('compileLib',
|
|
79
|
+
gulp.series(
|
|
80
|
+
[
|
|
81
|
+
'cleanLib', 'compileScss',
|
|
82
|
+
'moveScss',
|
|
83
|
+
gulp.parallel('compileTSForESM', 'compileTSForCJS'),
|
|
84
|
+
]
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
gulp.task('findDupCSSVariables', function findDupCSSVariables() {
|
|
89
|
+
return gulp.src(['**/variable?.scss', '!node_modules/**/*.*'])
|
|
90
|
+
.pipe(through2.obj((chunk, enc, cb) => {
|
|
91
|
+
const fileStr = chunk.contents.toString(enc);
|
|
92
|
+
const lines = fileStr.split('\n');
|
|
93
|
+
const variables = new Set();
|
|
94
|
+
for (let line of lines) {
|
|
95
|
+
if (/\$[a-z]+(-[a-z0-9_]+)+/.test(line)) {
|
|
96
|
+
const variable = line.split(':')[0];
|
|
97
|
+
if (variables.has(variable)) {
|
|
98
|
+
console.error(`❌ ${variable} dup`);
|
|
99
|
+
} else {
|
|
100
|
+
variables.add(variable);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
cb();
|
|
105
|
+
}));
|
|
106
|
+
});
|
|
107
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const esbuild = require('esbuild');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const compileWorker = async ()=>{
|
|
9
|
+
const workerEntry = path.join(__dirname, "..", "core/src/worker/json.worker.ts");
|
|
10
|
+
|
|
11
|
+
const result = await esbuild.build({
|
|
12
|
+
entryPoints: [workerEntry],
|
|
13
|
+
bundle: true,
|
|
14
|
+
write: false,
|
|
15
|
+
});
|
|
16
|
+
return result.outputFiles[0].text;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
const buildMain = async ()=>{
|
|
21
|
+
const mainEntry = path.join(__dirname, "..", "core/src/index.ts");
|
|
22
|
+
|
|
23
|
+
const result = await esbuild.build({
|
|
24
|
+
entryPoints: [mainEntry],
|
|
25
|
+
bundle: true,
|
|
26
|
+
packages: 'external',
|
|
27
|
+
write: false,
|
|
28
|
+
format: 'esm'
|
|
29
|
+
});
|
|
30
|
+
return result.outputFiles[0].text;
|
|
31
|
+
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
const compile = async ()=>{
|
|
37
|
+
const workerRaw = await compileWorker();
|
|
38
|
+
|
|
39
|
+
const mainRaw = await buildMain();
|
|
40
|
+
|
|
41
|
+
const finalRaw = mainRaw.replaceAll("%WORKER_RAW%", encodeURIComponent(workerRaw));
|
|
42
|
+
|
|
43
|
+
const saveDir = path.join(__dirname, "..", "core/lib");
|
|
44
|
+
|
|
45
|
+
if (!fs.existsSync(saveDir)) {
|
|
46
|
+
fs.mkdirSync(saveDir);
|
|
47
|
+
}
|
|
48
|
+
fs.writeFileSync(path.join(saveDir, "index.js"), finalRaw, 'utf8');
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
compile();
|
|
@@ -523,6 +523,7 @@ $module: #{$prefix}-aiChatInput;
|
|
|
523
523
|
|
|
524
524
|
.input-slot {
|
|
525
525
|
display: inline-block;
|
|
526
|
+
box-sizing: content-box;
|
|
526
527
|
background-color: $color-aiChatInput_rich_text-input_slot-bg;
|
|
527
528
|
border-radius: $radius-aiChatInput_rich_text-input_slot;
|
|
528
529
|
padding: $spacing-aiChatInput_rich_text-input_slot-paddingY $spacing-aiChatInput_rich_text-input_slot-paddingX;
|
|
@@ -13,7 +13,11 @@ const strings = exports.strings = {
|
|
|
13
13
|
ZERO_WIDTH_CHAR: '\uFEFF',
|
|
14
14
|
PIC_PREFIX: 'image/',
|
|
15
15
|
PIC_SUFFIX_ARRAY: ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'],
|
|
16
|
-
DELETABLE: 'skipCustomTransactionPlugin'
|
|
16
|
+
DELETABLE: 'skipCustomTransactionPlugin',
|
|
17
|
+
SEND_HOTKEY: {
|
|
18
|
+
'ENTER': 'enter',
|
|
19
|
+
'SHIFT_ENTER': 'shift+enter'
|
|
20
|
+
}
|
|
17
21
|
};
|
|
18
22
|
const numbers = exports.numbers = {
|
|
19
23
|
SCROLL_AMOUNT: 300,
|
|
@@ -325,6 +325,9 @@ class AIChatInputFoundation extends _foundation.default {
|
|
|
325
325
|
this.handRichTextArealKeyDown = (view, event) => {
|
|
326
326
|
var _a;
|
|
327
327
|
// console.log('outer key down handle');
|
|
328
|
+
const {
|
|
329
|
+
sendHotKey
|
|
330
|
+
} = this.getProps();
|
|
328
331
|
const {
|
|
329
332
|
suggestionVisible,
|
|
330
333
|
skillVisible
|
|
@@ -341,11 +344,11 @@ class AIChatInputFoundation extends _foundation.default {
|
|
|
341
344
|
}
|
|
342
345
|
const editor = (_a = this._adapter.getEditor()) !== null && _a !== void 0 ? _a : {};
|
|
343
346
|
const allowHotKeySend = (0, _get2.default)(editor, 'storage.SemiAIChatInput.allowHotKeySend');
|
|
344
|
-
if (event.key === 'Enter' && !event.shiftKey && allowHotKeySend) {
|
|
347
|
+
if (event.key === 'Enter' && (sendHotKey === _constants.strings.SEND_HOTKEY.ENTER ? !event.shiftKey : event.shiftKey) && allowHotKeySend) {
|
|
345
348
|
this.handleSend();
|
|
346
349
|
return true;
|
|
347
350
|
}
|
|
348
|
-
if (event.key === 'Enter' && event.shiftKey) {
|
|
351
|
+
if (event.key === 'Enter' && (sendHotKey === _constants.strings.SEND_HOTKEY.ENTER ? event.shiftKey : !event.shiftKey)) {
|
|
349
352
|
/**
|
|
350
353
|
* Tiptap 默认情况下 Enter + Shift 时候是使用 <br /> 实现换行
|
|
351
354
|
* 为保证自定义的一些逻辑生效(比如零宽字符的插入),Enter + Shift 希望实现通过新建 p 标签的方式完成换行
|
|
@@ -75,8 +75,14 @@ class InputBoxFoundation extends _foundation.default {
|
|
|
75
75
|
attachment
|
|
76
76
|
} = this.getStates();
|
|
77
77
|
const {
|
|
78
|
-
disableSend: disableSendInProps
|
|
78
|
+
disableSend: disableSendInProps,
|
|
79
|
+
canSend
|
|
79
80
|
} = this.getProps();
|
|
81
|
+
// 如果用户设置了 canSend API,则使用 canSend 值
|
|
82
|
+
// If the user has configured the canSend API, then the canSend value will be used.
|
|
83
|
+
if (typeof canSend === 'boolean') {
|
|
84
|
+
return !canSend;
|
|
85
|
+
}
|
|
80
86
|
/** 不能发送的条件:(满足任1)
|
|
81
87
|
* 1. props 中禁止发送;2. 没有文本输入,且没有上传文件; 3.上传文件中有状态不为 success 的
|
|
82
88
|
* Conditions under which content cannot be sent: (any one of the following conditions must be met)
|
|
@@ -33,6 +33,7 @@ declare class TagInputFoundation extends BaseFoundation<TagInputAdapter> {
|
|
|
33
33
|
*/
|
|
34
34
|
handleInputChange: (e: TagInputChangeEvent) => void;
|
|
35
35
|
handleInputCompositionStart: (e: any) => void;
|
|
36
|
+
_splitArray: (originString: string, separators: string | string[] | null) => any;
|
|
36
37
|
handleInputCompositionEnd: (e: any) => void;
|
|
37
38
|
/**
|
|
38
39
|
* check whether the input change is legal
|
|
@@ -49,6 +49,15 @@ class TagInputFoundation extends _foundation.default {
|
|
|
49
49
|
}
|
|
50
50
|
this._adapter.setEntering(true);
|
|
51
51
|
};
|
|
52
|
+
this._splitArray = (originString, separators) => {
|
|
53
|
+
const {
|
|
54
|
+
split
|
|
55
|
+
} = this.getProps();
|
|
56
|
+
if ((0, _isFunction2.default)(split)) {
|
|
57
|
+
return split(originString, separators);
|
|
58
|
+
}
|
|
59
|
+
return (0, _getSplitedArray.default)(originString, separators);
|
|
60
|
+
};
|
|
52
61
|
this.handleInputCompositionEnd = e => {
|
|
53
62
|
const {
|
|
54
63
|
value
|
|
@@ -63,7 +72,7 @@ class TagInputFoundation extends _foundation.default {
|
|
|
63
72
|
}
|
|
64
73
|
this._adapter.setEntering(false);
|
|
65
74
|
let allowChange = true;
|
|
66
|
-
const inputArr =
|
|
75
|
+
const inputArr = this._splitArray(value, separator);
|
|
67
76
|
let index = 0;
|
|
68
77
|
for (; index < inputArr.length; index++) {
|
|
69
78
|
if (inputArr[index].length > maxLength) {
|
|
@@ -100,8 +109,8 @@ class TagInputFoundation extends _foundation.default {
|
|
|
100
109
|
} = this._adapter.getStates();
|
|
101
110
|
let allowChange = true;
|
|
102
111
|
if ((0, _isNumber2.default)(maxLength)) {
|
|
103
|
-
const valueArr =
|
|
104
|
-
const inputArr =
|
|
112
|
+
const valueArr = this._splitArray(value, separator);
|
|
113
|
+
const inputArr = this._splitArray(inputValue, separator);
|
|
105
114
|
const maxLen = Math.max(valueArr.length, inputArr.length);
|
|
106
115
|
for (let i = 0; i < maxLen; i++) {
|
|
107
116
|
// When the input length is increasing
|
|
@@ -154,7 +163,7 @@ class TagInputFoundation extends _foundation.default {
|
|
|
154
163
|
inputValue,
|
|
155
164
|
tagsArray
|
|
156
165
|
} = this._adapter.getStates();
|
|
157
|
-
let addTags =
|
|
166
|
+
let addTags = this._splitArray(inputValue, separator);
|
|
158
167
|
addTags = addTags.filter((item, idx) => {
|
|
159
168
|
// If allowDuplicates is false, then filter duplicates
|
|
160
169
|
if (!allowDuplicates) {
|
|
@@ -523,6 +523,7 @@ $module: #{$prefix}-aiChatInput;
|
|
|
523
523
|
|
|
524
524
|
.input-slot {
|
|
525
525
|
display: inline-block;
|
|
526
|
+
box-sizing: content-box;
|
|
526
527
|
background-color: $color-aiChatInput_rich_text-input_slot-bg;
|
|
527
528
|
border-radius: $radius-aiChatInput_rich_text-input_slot;
|
|
528
529
|
padding: $spacing-aiChatInput_rich_text-input_slot-paddingY $spacing-aiChatInput_rich_text-input_slot-paddingX;
|
|
@@ -7,7 +7,11 @@ const strings = {
|
|
|
7
7
|
ZERO_WIDTH_CHAR: '\uFEFF',
|
|
8
8
|
PIC_PREFIX: 'image/',
|
|
9
9
|
PIC_SUFFIX_ARRAY: ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'],
|
|
10
|
-
DELETABLE: 'skipCustomTransactionPlugin'
|
|
10
|
+
DELETABLE: 'skipCustomTransactionPlugin',
|
|
11
|
+
SEND_HOTKEY: {
|
|
12
|
+
'ENTER': 'enter',
|
|
13
|
+
'SHIFT_ENTER': 'shift+enter'
|
|
14
|
+
}
|
|
11
15
|
};
|
|
12
16
|
const numbers = {
|
|
13
17
|
SCROLL_AMOUNT: 300,
|
|
@@ -2,7 +2,7 @@ import _isString from "lodash/isString";
|
|
|
2
2
|
import _isNumber from "lodash/isNumber";
|
|
3
3
|
import _get from "lodash/get";
|
|
4
4
|
import BaseFoundation from '../base/foundation';
|
|
5
|
-
import { cssClasses } from './constants';
|
|
5
|
+
import { cssClasses, strings } from './constants';
|
|
6
6
|
import { findSkillSlotInString, getSkillSlotString, transformJSONResult } from './utils';
|
|
7
7
|
const prefixCls = cssClasses.PREFIX;
|
|
8
8
|
export default class AIChatInputFoundation extends BaseFoundation {
|
|
@@ -318,6 +318,9 @@ export default class AIChatInputFoundation extends BaseFoundation {
|
|
|
318
318
|
this.handRichTextArealKeyDown = (view, event) => {
|
|
319
319
|
var _a;
|
|
320
320
|
// console.log('outer key down handle');
|
|
321
|
+
const {
|
|
322
|
+
sendHotKey
|
|
323
|
+
} = this.getProps();
|
|
321
324
|
const {
|
|
322
325
|
suggestionVisible,
|
|
323
326
|
skillVisible
|
|
@@ -334,11 +337,11 @@ export default class AIChatInputFoundation extends BaseFoundation {
|
|
|
334
337
|
}
|
|
335
338
|
const editor = (_a = this._adapter.getEditor()) !== null && _a !== void 0 ? _a : {};
|
|
336
339
|
const allowHotKeySend = _get(editor, 'storage.SemiAIChatInput.allowHotKeySend');
|
|
337
|
-
if (event.key === 'Enter' && !event.shiftKey && allowHotKeySend) {
|
|
340
|
+
if (event.key === 'Enter' && (sendHotKey === strings.SEND_HOTKEY.ENTER ? !event.shiftKey : event.shiftKey) && allowHotKeySend) {
|
|
338
341
|
this.handleSend();
|
|
339
342
|
return true;
|
|
340
343
|
}
|
|
341
|
-
if (event.key === 'Enter' && event.shiftKey) {
|
|
344
|
+
if (event.key === 'Enter' && (sendHotKey === strings.SEND_HOTKEY.ENTER ? event.shiftKey : !event.shiftKey)) {
|
|
342
345
|
/**
|
|
343
346
|
* Tiptap 默认情况下 Enter + Shift 时候是使用 <br /> 实现换行
|
|
344
347
|
* 为保证自定义的一些逻辑生效(比如零宽字符的插入),Enter + Shift 希望实现通过新建 p 标签的方式完成换行
|
|
@@ -68,8 +68,14 @@ export default class InputBoxFoundation extends BaseFoundation {
|
|
|
68
68
|
attachment
|
|
69
69
|
} = this.getStates();
|
|
70
70
|
const {
|
|
71
|
-
disableSend: disableSendInProps
|
|
71
|
+
disableSend: disableSendInProps,
|
|
72
|
+
canSend
|
|
72
73
|
} = this.getProps();
|
|
74
|
+
// 如果用户设置了 canSend API,则使用 canSend 值
|
|
75
|
+
// If the user has configured the canSend API, then the canSend value will be used.
|
|
76
|
+
if (typeof canSend === 'boolean') {
|
|
77
|
+
return !canSend;
|
|
78
|
+
}
|
|
73
79
|
/** 不能发送的条件:(满足任1)
|
|
74
80
|
* 1. props 中禁止发送;2. 没有文本输入,且没有上传文件; 3.上传文件中有状态不为 success 的
|
|
75
81
|
* Conditions under which content cannot be sent: (any one of the following conditions must be met)
|
|
@@ -33,6 +33,7 @@ declare class TagInputFoundation extends BaseFoundation<TagInputAdapter> {
|
|
|
33
33
|
*/
|
|
34
34
|
handleInputChange: (e: TagInputChangeEvent) => void;
|
|
35
35
|
handleInputCompositionStart: (e: any) => void;
|
|
36
|
+
_splitArray: (originString: string, separators: string | string[] | null) => any;
|
|
36
37
|
handleInputCompositionEnd: (e: any) => void;
|
|
37
38
|
/**
|
|
38
39
|
* check whether the input change is legal
|
|
@@ -42,6 +42,15 @@ class TagInputFoundation extends BaseFoundation {
|
|
|
42
42
|
}
|
|
43
43
|
this._adapter.setEntering(true);
|
|
44
44
|
};
|
|
45
|
+
this._splitArray = (originString, separators) => {
|
|
46
|
+
const {
|
|
47
|
+
split
|
|
48
|
+
} = this.getProps();
|
|
49
|
+
if (_isFunction(split)) {
|
|
50
|
+
return split(originString, separators);
|
|
51
|
+
}
|
|
52
|
+
return getSplitedArray(originString, separators);
|
|
53
|
+
};
|
|
45
54
|
this.handleInputCompositionEnd = e => {
|
|
46
55
|
const {
|
|
47
56
|
value
|
|
@@ -56,7 +65,7 @@ class TagInputFoundation extends BaseFoundation {
|
|
|
56
65
|
}
|
|
57
66
|
this._adapter.setEntering(false);
|
|
58
67
|
let allowChange = true;
|
|
59
|
-
const inputArr =
|
|
68
|
+
const inputArr = this._splitArray(value, separator);
|
|
60
69
|
let index = 0;
|
|
61
70
|
for (; index < inputArr.length; index++) {
|
|
62
71
|
if (inputArr[index].length > maxLength) {
|
|
@@ -93,8 +102,8 @@ class TagInputFoundation extends BaseFoundation {
|
|
|
93
102
|
} = this._adapter.getStates();
|
|
94
103
|
let allowChange = true;
|
|
95
104
|
if (_isNumber(maxLength)) {
|
|
96
|
-
const valueArr =
|
|
97
|
-
const inputArr =
|
|
105
|
+
const valueArr = this._splitArray(value, separator);
|
|
106
|
+
const inputArr = this._splitArray(inputValue, separator);
|
|
98
107
|
const maxLen = Math.max(valueArr.length, inputArr.length);
|
|
99
108
|
for (let i = 0; i < maxLen; i++) {
|
|
100
109
|
// When the input length is increasing
|
|
@@ -147,7 +156,7 @@ class TagInputFoundation extends BaseFoundation {
|
|
|
147
156
|
inputValue,
|
|
148
157
|
tagsArray
|
|
149
158
|
} = this._adapter.getStates();
|
|
150
|
-
let addTags =
|
|
159
|
+
let addTags = this._splitArray(inputValue, separator);
|
|
151
160
|
addTags = addTags.filter((item, idx) => {
|
|
152
161
|
// If allowDuplicates is false, then filter duplicates
|
|
153
162
|
if (!allowDuplicates) {
|
package/package.json
CHANGED
|
@@ -1,30 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@douyinfe/semi-foundation",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.90.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"clean": "rimraf lib",
|
|
7
6
|
"build:lib": "node ./scripts/compileLib.js",
|
|
8
|
-
"prepublishOnly": "npm run
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"lib/*",
|
|
12
|
-
"**/*.ts",
|
|
13
|
-
"**/*.scss",
|
|
14
|
-
"!**/node_modules/**",
|
|
15
|
-
"!**/*.test.ts",
|
|
16
|
-
"!**/*.spec.ts"
|
|
17
|
-
],
|
|
18
|
-
"typesVersions": {
|
|
19
|
-
"*": {
|
|
20
|
-
"*": [
|
|
21
|
-
"lib/es/*"
|
|
22
|
-
]
|
|
23
|
-
}
|
|
7
|
+
"prepublishOnly": "npm run build:lib"
|
|
24
8
|
},
|
|
25
9
|
"dependencies": {
|
|
26
|
-
"@douyinfe/semi-animation": "2.
|
|
27
|
-
"@douyinfe/semi-json-viewer-core": "2.
|
|
10
|
+
"@douyinfe/semi-animation": "2.90.0",
|
|
11
|
+
"@douyinfe/semi-json-viewer-core": "2.90.0",
|
|
28
12
|
"@mdx-js/mdx": "^3.0.1",
|
|
29
13
|
"async-validator": "^3.5.0",
|
|
30
14
|
"classnames": "^2.2.6",
|
|
@@ -45,7 +29,7 @@
|
|
|
45
29
|
"*.scss",
|
|
46
30
|
"*.css"
|
|
47
31
|
],
|
|
48
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "a8f13664fba5c558e4ab14ecb3f12006eba22319",
|
|
49
33
|
"devDependencies": {
|
|
50
34
|
"@babel/plugin-transform-runtime": "^7.15.8",
|
|
51
35
|
"@babel/preset-env": "^7.15.8",
|
|
@@ -61,7 +45,6 @@
|
|
|
61
45
|
"gulp-sass": "^5.0.0",
|
|
62
46
|
"gulp-typescript": "^6.0.0-alpha.1",
|
|
63
47
|
"merge2": "^1.4.1",
|
|
64
|
-
"rimraf": "^3.0.2",
|
|
65
48
|
"through2": "^4.0.2"
|
|
66
49
|
}
|
|
67
50
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const gulp = require('gulp');
|
|
2
|
+
require('../gulpfile');
|
|
3
|
+
|
|
4
|
+
function compileLib() {
|
|
5
|
+
const taskInstance = gulp.task('compileLib');
|
|
6
|
+
if (taskInstance === undefined) {
|
|
7
|
+
console.error('no task named compileLib registered');
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
taskInstance.apply(gulp);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
compileLib();
|
package/tagInput/foundation.ts
CHANGED
|
@@ -73,6 +73,14 @@ class TagInputFoundation extends BaseFoundation<TagInputAdapter> {
|
|
|
73
73
|
this._adapter.setEntering(true);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
_splitArray = (originString: string, separators: string | string[] | null) => {
|
|
77
|
+
const { split } = this.getProps();
|
|
78
|
+
if (isFunction(split)) {
|
|
79
|
+
return split(originString, separators);
|
|
80
|
+
}
|
|
81
|
+
return getSplitedArray(originString, separators);
|
|
82
|
+
}
|
|
83
|
+
|
|
76
84
|
handleInputCompositionEnd = (e: any) => {
|
|
77
85
|
const { value } = e.target;
|
|
78
86
|
const {
|
|
@@ -85,7 +93,7 @@ class TagInputFoundation extends BaseFoundation<TagInputAdapter> {
|
|
|
85
93
|
}
|
|
86
94
|
this._adapter.setEntering(false);
|
|
87
95
|
let allowChange = true;
|
|
88
|
-
const inputArr =
|
|
96
|
+
const inputArr = this._splitArray(value, separator);
|
|
89
97
|
let index = 0;
|
|
90
98
|
for (; index < inputArr.length; index++) {
|
|
91
99
|
if (inputArr[index].length > maxLength) {
|
|
@@ -121,8 +129,8 @@ class TagInputFoundation extends BaseFoundation<TagInputAdapter> {
|
|
|
121
129
|
const { inputValue } = this._adapter.getStates();
|
|
122
130
|
let allowChange = true;
|
|
123
131
|
if (isNumber(maxLength)) {
|
|
124
|
-
const valueArr =
|
|
125
|
-
const inputArr =
|
|
132
|
+
const valueArr = this._splitArray(value, separator);
|
|
133
|
+
const inputArr = this._splitArray(inputValue, separator);
|
|
126
134
|
const maxLen = Math.max(valueArr.length, inputArr.length);
|
|
127
135
|
for (let i = 0; i < maxLen; i++) {
|
|
128
136
|
// When the input length is increasing
|
|
@@ -174,7 +182,7 @@ class TagInputFoundation extends BaseFoundation<TagInputAdapter> {
|
|
|
174
182
|
inputValue,
|
|
175
183
|
tagsArray
|
|
176
184
|
} = this._adapter.getStates();
|
|
177
|
-
let addTags =
|
|
185
|
+
let addTags = this._splitArray(inputValue, separator);
|
|
178
186
|
|
|
179
187
|
addTags = addTags.filter((item, idx) => {
|
|
180
188
|
// If allowDuplicates is false, then filter duplicates
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2015",
|
|
4
|
+
"baseUrl": "./",
|
|
5
|
+
"outDir": "lib",
|
|
6
|
+
"sourceMap": true,
|
|
7
|
+
"allowJs": true,
|
|
8
|
+
"module": "es6",
|
|
9
|
+
"lib": ["esnext", "dom"],
|
|
10
|
+
"moduleResolution": "node",
|
|
11
|
+
"noImplicitAny": false,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"allowSyntheticDefaultImports": true,
|
|
14
|
+
"experimentalDecorators": true,
|
|
15
|
+
"noImplicitReturns": true,
|
|
16
|
+
"noImplicitThis": false,
|
|
17
|
+
"strictNullChecks": false,
|
|
18
|
+
"esModuleInterop": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"declaration": true,
|
|
21
|
+
"strict": true
|
|
22
|
+
},
|
|
23
|
+
"include": ["**/*.ts"],
|
|
24
|
+
"exclude": ["node_modules"]
|
|
25
|
+
}
|